I’m trying to enable a default constructor only if the class’s template
parameter is floating point. Note T
is not a parameter type nor return type
but the class template type.
template <typename T>
struct Thing
{
const T x;
Thing( T t) : x(t) {}
//only turn on this constructor if T is floating point
Thing() : x(std::numeric_limits<T>::quiet_NaN()) {}
};
//...
Thing<double> dt;
Thing<float> ft;
Thing<int> it1;
Thing<int> it2(3);
I tried putting the following in front of the constructor
template <std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
And I tried putting the std::enable_if_t...= true
stuff as an argument to the
default constructor (and various other attempts).
Both of these tries rightfully complains about it1
so that’s good, but when I remove that, they both also complain about it2
! I don’t understand and can’t find the magic incantation.
Thanks for any insights.
I forgot to mention, I’m stuck on C++17.
>Solution :
Use requires
:
Thing() requires std::is_floating_point_v<T>
: x(std::numeric_limits<T>::quiet_NaN())
{}
Or, in C++17:
template <typename U = T, std::enable_if_t<std::is_floating_point_v<U>, std::nullptr_t> = nullptr>
Thing()
: x(std::numeric_limits<T>::quiet_NaN())
{}
The SFINAE condition must depend on a template parameter of the function itself. Otherwise it can be checked when the class is first instantiated, even if the function isn’t used.
I also tweaked a few things, purely for style.