
Hi all, I was quite impressed by Sean Parent's Friday talk in C++Now! 2012 (see slides in [1], code in [2]) and was left wondering whether the generation of his polymorphic object wrapper could be made simple somehow in C++11. [1]: https://github.com/boostcon/cppnow_presentations_2012/raw/master/fri/value_s... [2]: https://github.com/boostcon/cppnow_presentations_2012/blob/master/fri/value_... What I ended up with is tricking ADL into allowing the overloading of arbitrary (specifically crafted) function objects that I call _callables_, and then letting the user define interfaces by specifying sets of ("member") function signatures with a callable. You can find the code, and my rambling introductory README file, in GitHub: https://github.com/pyrtsa/poly Comments are welcome! * * * Here's a somewhat shorter intro: 1) Create a callable F by simply deriving it from poly::callable<F>: struct draw_ : poly::callable<draw_> {}; constexpr draw_ draw = {}; 2) Or use the convenience macro POLY_CALLABLE(name) to do the same: POLY_CALLABLE(to_string); // type `to_string_` and object `to_string` 3) Overload your callables by overloading the function named `call`, with the callable as first argument: template <typename T> void call(draw_, T const & x, std::ostream & out, std::size_t position) { out << std::string(position, ' ') << x << std::endl; } std::string call(to_string_, int i) { return std::to_string(i); } template <typename T> std::string call(to_string_, std::vector<T> const & xs) { std::ostringstream s; s << '['; auto i = begin(xs), e = end(xs); if (i != e) s << *i++; while (i != e) s << ", " << *i++; s << ']'; return s.str(); } Now you can call ::draw(x, o, p) and ::to_string(x) for several different types of x: ::draw(123, std::cout, 2); // prints " 123" to stdout ::to_string(std::vector<int>(1, 2, 3)); // "[1, 2, 3]" But you can likewise extend ::draw and ::to_string further by overloading them for your own types too. 4) Define an interface by specifying the set of function signatures as template arguments to poly::interface: using drawable = poly::interface< void(draw_, poly::self const &, std::ostream &, std::size_t, std::string(to_string_, poly::self const &)>; Now, the following calls got automatically defined, and forwarded to whatever type you successfully construct a `drawable` from: void call(draw_, drawable const &, std::ostream &, std::size_t); std::string call(to_string_, drawable const &); * * * I am aware that Steven Watanabe has put some astonishing work on his proposed Boost.TypeErasure. I'm open for discussion whether and how his or mine is a better approach, or if we could combine these into an eventual Boost.Interface library or such! * * * PS. Like I mention in my GitHub page, this kind of type erasure is common in functional languages like Haskell or Clojure. The problem they are solving there is known as the Expression Problem. IMO it makes very much sense to have the corresponding construct in C++ too, as we're moving towards a more and more functional style with parallelism and such. Best Regards, -- Pyry Jahkola pyry.jahkola@iki.fi https://twitter.com/pyrtsa