I've got two sets of code, the first of which compiles and behaves as expected, but is [appearing to be] needlessly verbose:
template<point_type type, typename T>
struct point2d_base {
std::enable_if_t<std::is_arithmetic_v<T>, T> x, y;
template<point_type t2 = type>
point2d_base(std::enable_if_t<t2 == point_type::generic, T> x = 0, T y = 0) :
x(x), y(y) {}
template<point_type t2 = type>
explicit point2d_base(std::enable_if_t<t2 != point_type::generic, T> x = 0, T y = 0) :
x(x), y(y) {}
/*Some unrelated code*/
};
This is the code I'd rather write, but I get many, many compile errors if I do it like this:
template<point_type type, typename T>
struct point2d_base {
std::enable_if_t<std::is_arithmetic_v<T>, T> x, y;
point2d_base(std::enable_if_t<type == point_type::generic, T> x = 0, T y = 0) :
x(x), y(y) {}
explicit point2d_base(std::enable_if_t<type != point_type::generic, T> x = 0, T y = 0) :
x(x), y(y) {}
/*Some unrelated code*/
};
For reference sake, point_type
is an "Enum Class" that contains three values: generic
, corner
, center
.
My question is: Why does the first code compile, and the second doesn't?
You can't rely on your template class parameters for using
std::enable_if
. If you want to usestd::enable_if
with a function, you have to make that function a template function. It's because when you class template is instantiated all member function of that class instantiate too. You need a template member function to conditionally enable that function or not. (It's my guess and I think is correct)