std::enable_if : parameter vs template parameter
Default template arguments are not part of the signature of a template (so both definitions try to define the same template twice). Their parameter types are part of the signature, however. So you can do
template <class T>
class check
{
public:
template< class U = T,
typename std::enable_if<std::is_same<U, int>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getInt();
}
template< class U = T,
typename std::enable_if<std::is_same<U, double>::value, int>::type = 0>
inline static U readVal()
{
return BuffCheck.getDouble();
}
};
The problem is that the compiler sees 2 overloads of the same method, both which contain the same arguments(none, in this case) and the same return value. You can't provide such definition. The cleanest way to do this is to use SFINAE on the function's return value:
template <class T>
class check
{
public:
template< class U = T>
static typename std::enable_if<std::is_same<U, int>::value, U>::type readVal()
{
return BuffCheck.getInt();
}
template< class U = T>
static typename std::enable_if<std::is_same<U, double>::value, U>::type readVal()
{
return BuffCheck.getDouble();
}
};
That way, you're providing 2 different overloads. One returns an int, the other one returns a double, and only one can be instantiated using a certain T.
I know this question is about std::enable_if
, however, I like to provide an alternative solution to solve the same problem without enable_if. It does require C++17
template <class T>
class check
{
public:
inline static T readVal()
{
if constexpr (std::is_same_v<T, int>)
return BuffCheck.getInt();
else if constexpr (std::is_same_v<T, double>)
return BuffCheck.getDouble();
}
};
This code looks more as if you would write it at runtime. All branches have to be syntactic correct, however the semantics don't have to be. In this case, if T is int, the getDouble ain't causing compilation errors (or warnings) as it doesn't get checked/used by the compiler.
If the return type of the function would be to complex to mention, you can always use auto
as the return type.