Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++-14 using enable_if_t to select member function of class templated on integral type

I am trying to enable different member functions based on an integral class template parameter like so:

#include <type_traits>

template<int Dimension>
struct Foo
{
    template<std::enable_if_t<Dimension == 1> = 0>
    int bar(int i) const { return i; }

    template<std::enable_if_t<Dimension == 2> = 0>
    int bar(int i, int j) const { return i + j; }
};

int main(int argc, const char **argv)
{
    Foo<1> a;
    a.bar(1);

    Foo<2> b;
    b.bar(1,2);

    return 0;
}

Using gcc5 in c++-14 mode, it fails to compile with the following errors:

tools/t1.cpp: In instantiation of 'struct Foo<1>':
tools/t1.cpp:18:12:   required from here
tools/t1.cpp:13:9: error: no type named 'type' in 'struct std::enable_if<false, int>'
     int bar(int i, int j) const { return i + j; }
         ^
tools/t1.cpp: In instantiation of 'struct Foo<2>':
tools/t1.cpp:21:12:   required from here
tools/t1.cpp:10:9: error: no type named 'type' in 'struct std::enable_if<false, int>'
     int bar(int i) const { return i; }

These seem to indicated the SFINAE is not doing what I expect since the enable_if_t seems to be working correctly.

In this trivial example, overloading would work as well, but in my actual use case I need to hide the functions to prevent accidental use and / or compilation errors depending on the circumstance.

What am I missing with SFINAE here?

like image 655
RandomBits Avatar asked Feb 07 '23 03:02

RandomBits


1 Answers

Substitution failure is not an elephant when it happens during template argument deduction.

Also, enable_if_t<true> is void, and you can't have a void template non-type parameter.

Defer evaluation with a default template argument:

template<int Dimension>
struct Foo
{
    template<int..., int I = Dimension, std::enable_if_t<I == 1, int> = 0>
    int bar(int i) const { return i; }
    // etc.
};

The unnamed parameter packint... guards against attempts to explicitly specify I.

like image 76
T.C. Avatar answered Feb 16 '23 02:02

T.C.