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?
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With