In C++14, take 3 generic arguments, forward them to a tuple, forward that tuple to a new constructor (possibly with a tag type to aid dispatch), and use the type-based std::get to exctract each type. Forward that to yet another constructor, with a tag to aid in dispatchimg.
SFINAE checks to provide for early failure optional.
struct Date { private: struct as_tuple{}; struct in_order{}; public: template<class A,class B,class C, // SFINAE test based on type_index below: class=decltype( type_index<Year,A,B,C>{}+type_index<Month,A,B,C>{}+type_index<Day,A,B,C>{} ) > Date(A a,B b,C c): Date(as_tuple{}, std::make_tuple(std::move(a),std::move(b),std::move(c)) ) {} private: template<class...Ts> Date(as_tuple, std::tuple<Ts...> t): Date(in_order{}, std::get<Year>(t),std::get<Month>(t),std::get<Day>(t) ) {} Date(in_order,Year y_,Month m_,Day d_): y(y_),m(m_),d(d_) {} };
In C++11, you can implement your own equivalent of std::get<T>.
SFINAE checks that y/m/d are all present are harder, but maybe not needed.
Optimization (adding move/perfect forwarding) is another improvement that may not be needed if your y/m/d types are simple enough.
The technique of forwarding constructors and tags is based on the idea of doing one thing at a time, instead of all at once. The code is going to be already strange enough.
Implementing your own std::get<T> is easy. Making it SFINAE friendly a bit harder:
// helpers to keep code clean: template<std::size_t n> using size=std::integral_constant<std::size_t, n>; template<class T>struct tag{using type=T;}; template<class T, class...Ts> struct type_index_t{}; // SFINAE failure // client code uses this. Everything else can go in namespace details: template<class T, class...Ts> using type_index = typename type_index_t<T,Ts...>::type; // found a match! template<class T, class...Ts> struct type_index_t<T, T, Ts...>: tag<size<0>> {}; template<class T, class T0, class...Ts> struct type_index_t<T, T0, Ts...>: tag<size<type_index<T,Ts...>::value+1>> {}; // SFINAE (hopefully) std::get<T>: template<class T, class...Ts> auto my_get( std::tuple<Ts...>& tup ) -> decltype( std::get< type_index<T,Ts...>::value >(tup) ) { return std::get< type_index<T,Ts...>::value >(tup); } template<class T, class...Ts> auto my_get( std::tuple<Ts...> const& tup ) -> decltype( std::get< type_index<T,Ts...>::value >(tup) ) { return std::get< type_index<T,Ts...>::value >(tup); } template<class T, class...Ts> auto my_get( std::tuple<Ts...>&& tup ) -> decltype( std::get< type_index<T,Ts...>::value >(std::move(tup)) ) { return std::get< type_index<T,Ts...>::value >(std::move(tup)); }
but that is just an untested sketch. Looking at the proposals for C++14 std::get<Type> is probably a better idea.