
Hi all, I played a bit more with overloading and it started being annoying and error-prone to add more overloads of concept_map (with more arguments) so I wrote a small macro to 1) generate my overloads and 2) save myself the time reading compiler errors when I use BOOST_TYPE_ERASURE_MEMBER and make a mistake in the number of arguments. It's for C++11 (argument pack) as it's all I need at the moment but I suppose that with Boost.Preprocessor, it'd be for C++03 doable. Well, in case it'd be of any use to someone, here it is, with a small test (tested with g+ 4.5 with -std=c++0x). #include <boost/type_erasure/concept_interface.hpp> #include <boost/type_erasure/rebind_any.hpp> #include <boost/type_erasure/derived.hpp> #include <boost/type_erasure/is_placeholder.hpp> #include <boost/type_erasure/constructible.hpp> #include <boost/type_erasure/relaxed_match.hpp> #include <boost/type_erasure/any.hpp> #include <boost/type_erasure/builtin.hpp> #include <boost/type_erasure/any_cast.hpp> #include <boost/type_erasure/detail/macro.hpp> #include <boost/mpl/vector.hpp> #include <iostream> #ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES #define BOOST_TYPE_ERASURE_MEMBER_VARIADIC_I(qualname,concept_name,member) \ BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qualname) \ template <typename T, typename... Args> \ struct concept_name{ \ static void apply(const T& t, const Args... a) { t.member(a...); } }; \ BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qualname) \ namespace boost { namespace type_erasure { \ template<class T, typename... U, class Base, class Enable> \ struct concept_interface< BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U... >, Base, T, Enable> : Base { \ typedef void _fun_defined; \ void member(typename rebind_any<Base, U>::type... arg)const \ {call(BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>(), *this, arg...);} }; \ template<class T, typename... U, class Base> \ struct concept_interface< BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>, Base, T, typename Base::_fun_defined> : Base{ \ using Base::member; void member(typename rebind_any<Base, U
::type... arg)const \ {call(BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>(), *this, arg...);} }; \ }} #endif
#define BOOST_TYPE_ERASURE_MEMBER_VARIADIC(qualified_name,member) \ BOOST_TYPE_ERASURE_MEMBER_VARIADIC_I( \ qualified_name, \ BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)), qualified_name), \ member) // supports overloading, does not require any number of arguments BOOST_TYPE_ERASURE_MEMBER_VARIADIC((n1)(n2)(foo),foo) namespace mpl = boost::mpl; using namespace boost::type_erasure; struct Test { void foo()const { std::cout << "foo() called" << std::endl; } void foo(int i)const { std::cout << "foo(int) called with: " << i << std::endl; } void foo(int i,char c)const { std::cout << "foo(int,char) called with: " << i << "," << c << std::endl; } void foo(double d)const { std::cout << "foo(double) called with: " << d << std::endl; } void foo(int i,double d)const { std::cout << "foo(int,double) called with: " << i << "," << d << std::endl; } void foo(int i,double d,char c)const { std::cout << "foo(int,double,char) called with: " << i << "," << d << "," << c << std::endl; } }; int main() { Test t; any< mpl::vector< n1::n2::foo<_self>, n1::n2::foo<_self, int>, n1::n2::foo<_self, double>, n1::n2::foo<_self, int, double>, n1::n2::foo<_self, int, char>, n1::n2::foo<_self, int, double, char>, copy_constructible<> > > x (t); x.foo(); // calls foo() x.foo(1); // calls foo(int) x.foo(1.0); // calls foo(double) x.foo(1,1.0); // calls foo(int, double) x.foo(1,'a'); // calls foo(int, char) x.foo(1,1.0,'a'); // calls foo(int, double,char) return 0; }