Template Metaprogramming w/Type Traits: Why does the first code compile and the second doesn't?

144 views Asked by At

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?

1

There are 1 answers

2
MRB On BEST ANSWER

You can't rely on your template class parameters for using std::enable_if. If you want to use std::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)