
On Sat, May 11, 2013 at 9:37 PM, Michael Marcin
I have a class that I want to have accept 0-5 arguments in any order for it's constructor. Each argument is a const references to one of 5 possible class types. All arguments must be distinct in type, passing the same type twice in an error. Passing an argument that is not one of the 5 supported types is also an error.
How do you go about implementing something like this?
I figure first you have to create a constructor for each arity but then how do you constrain the constructors as described above? I imagine it would involve enable_if.
class widget { widget();
template< class A > widget( const A& a );
template< class A, class B > widget( const A& a, const B& b );
template< class A, class B, class C > widget( const A& a, const B& b, const C& c );
template< class A, class B, class C, class D > widget( const A& a, const B& b, const C& c, const D& d );
template< class A, class B, class C, class D, class E > widget( const A& a, const B& b, const C& c, const D& d, const E& e ); };
To strictly address the problem above: First, decide if you really need to constrain the constructor signatures, or if it's sufficient to just static_assert on misuse. If you really need the former, you can make it work with enable_if. Now, determining whether the template binding is "valid" (as defined above)? I can't think of a super simple way to do this. But there is a way; I'm thinking of using Boost.MPL. Something like: typedef mpl::set< /*fill in your 5 types here*/ > my_types; template< class I, class End, class Seen > struct is_valid_iterate : mpl::eval_if_c< mpl::contains< my_types, typename mpl::deref<I>::type >::value && !mpl::contains< Seen, typename mpl::deref<I>::type >::value, is_valid_iterate< typename mpl::next<I>::type, End, typename mpl::push_back< Seen, typename mpl::deref<I>::type >::type >, mpl::false_ > { }; template< class End, class Seen > struct is_valid_iterate : mpl::true_ { }; template< class V > struct is_valid : is_valid_iterate< typename mpl::begin<V>::type, typename mpl::end<V>::type, mpl::set0<> > { }; Now, I'm not sure if there's an mpl::contains, but it would be easy enough to write; and you can probably shorten this a bit by only typing out mpl::deref<I>::type once; but that's the basic idea to one approach. This is entirely just a sketch so there might be some incorrect details but hopefully it conveys the idea. Now, whether the original problem you posed is *really* the problem you want to solve is another story... :) HTH, - Jeff