This is similar to @BryanChen's answer, but a cleaner IMO :) You can use inheritance to improve ambiguity resolution and move enable_if into the constructor template arguments.
#include <iostream> #include <string> #include <type_traits> using namespace std; template <int N> class Disambiguator; template<> class Disambiguator<0>{}; template <int N> class Disambiguator : public Disambiguator<N-1>{}; using Disambiguate = Disambiguator<100>; template< typename type_1, typename type_2 > struct result { template <typename T, typename U> using IsSame = typename enable_if<is_same<T, U>::value>::type; template <typename T, typename U> using IsNotSame = typename enable_if<!is_same<T, U>::value>::type; template <typename T = type_1, typename U = type_2, typename = IsNotSame<T,U>> result( type_1 f, Disambiguator<0>) : foo{f} {cout<<"NotSameType"<<endl;} template <typename T = type_1, typename U = type_2, typename = IsNotSame<T,U>> result( type_2 b, Disambiguator<1>) : bar{b} {cout<<"NotSameType"<<endl;} // I want to enable this constructor only if type_1 == type_2 template <typename T = type_1, typename U = type_2, typename = IsSame<T,U>> result( type_1 f, type_2 b ) : foo{f}, bar{b} {cout<<"SameType"<<endl;} // Other member functions removed. type_1 foo; type_2 bar; }; int main() { result<float, int> c(1.0, Disambiguate{}); result<float, int> i(0, Disambiguate{}); result<int, int> j(0, 0); result<string, int> s("abc", Disambiguate{}); result<string, int> si(0, Disambiguate{}); return 0; }
EDIT: You can read the idea of overloading @Xeo here . This is what I used in the above code.
source share