I'm trying to overload operator T()
using SFINAE to return a copy when T
is a fundamental type, and a const reference when T
is a class.
When using a double
in my example below, I can't get the 2nd overload (with std::is_class
) to be removed.
That is, the error I'm getting is:
error: no type named ‘type’ in ‘struct std::enable_if<false, const double&>’
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
^
What am I doing wrong?
#include <iostream>
#include <type_traits>
template<typename T>
struct Foo
{
operator typename std::enable_if<!std::is_class<T>::value, T >::type () const
{
return _val;
}
operator typename std::enable_if< std::is_class<T>::value, const T&>::type () const
{
return _val;
}
T _val;
};
int main()
{
Foo<double> f1;
f1._val = 0.3;
double d = f1;
std::cout << d << std::endl;
return 0;
}
T
is already known at the time your class member functions are instantiated, so no substitution occurs, and instead of SFINAE, you get a hard error. The easiest workaround is to introduce a dummy template parameter for those operator overloads and default it to T
so that type deduction can still occur.
template<typename U = T>
operator typename std::enable_if<!std::is_class<U>::value, U >::type () const
{
return _val;
}
template<typename U = T>
operator typename std::enable_if< std::is_class<U>::value, const U&>::type () const
{
return _val;
}