I already used the SFINAE idiom quite a few times and I got used to put my std::enable_if<> in template parameters rather than in return types. However, I
The = ... of the template just gives a default parameter. This is not part of the actual signature which looks like
template
auto foo(T a);
for both functions.
Depending on your needs, the most generic solution for this problem is using tag dispatching.
struct integral_tag { typedef integral_tag category; };
struct floating_tag { typedef floating_tag category; };
template struct foo_tag
: std::conditional::value, integral_tag,
typename std::conditional::value, floating_tag,
std::false_type>::type>::type {};
template
T foo_impl(T a, integral_tag) { return a; }
template
T foo_impl(T a, floating_tag) { return a; }
template
T foo(T a)
{
static_assert(!std::is_base_of >::value,
"T must be either floating point or integral");
return foo_impl(a, typename foo_tag::category{});
}
struct bigint {};
template<> struct foo_tag : integral_tag {};
int main()
{
//foo("x"); // produces a nice error message
foo(1);
foo(1.5);
foo(bigint{});
}