What are the differences between these classes? Precisely these methods with enable_if.
/// Alias of std::enable_if...
template <bool B, typename T = void>
using Enable_if = typename std::enable_if<B, T>::type;
Template<typename T, std::size_t N>
class A {
...
template <std::size_t NN = N,
typename = Enable_if<NN == 2>>
Some_Return_Type
method(param1, param2)
{}
template <std::size_t NN = N,
typename = Enable_if<NN == 1>>
Some_Return_Type
method(param1)
{}
};
Template<typename T, std::size_t N>
class B {
...
Enable_if<N == 2, Some_Return_Type>
method(param1, param2)
{}
Enable_if<N == 1, Some_Return_Type>
method(param1)
{}
};
What is the correct way to use enable_if in the case I have:
I would like to get something like:
Obj<int, 2> obj2;
Obj<int, 0> obj0;
Obj<int, 1> obj1;
if I write in the IDE obj0.
it shows only methods of N == 0
; obj1.
only N == 1
, ... .
Thanks.
std::enable_if can be used in many forms, including: as an additional function argument (not applicable to operator overloads) as a return type (not applicable to constructors and destructors) as a class template or function template parameter.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
Note that enable_if
is aimed to trigger SFINAE: if a template parameter substitution fails in its immediate context, it is not a compilation error.
This is exaclty what happens in class A
: when the user calls a.method(...)
, the compiler attempts to instantiate member function template method
, subsituting NN
parameter with a constant, which might fail.
However, in case of B::method
the "bad" substitution occurs during class template B
instantiation, when the compiler substitues N
. The failure occurs far from the parameter's immediate context, which is in this case template<typename T, std::size_t N> class B
.
That's why in the second case you will get a compilation error, rather than SFINAE.
So, to enable/disable member functions depending on the class template parameter, use the first approach, combining conditions as you wish. For instance:
template <typename T, std::size_t N>
class A {
template <std::size_t NN = N, typename = std::enable_if_t<NN == 2 || NN == 0>>
void method(int, int)
{}
template <std::size_t NN = N, typename = std::enable_if_t<NN == 1 || NN == 0>>
void method(int)
{}
};
UPDATE: How enable_if works. Roughly, one can implement it like this:
template<bool, class T = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> {
using type = T;
};
Note that if the first argument is false
, enable_if
doesn't have inner type
, so enable_if<false, int>::type
would be ill-formed. That's what triggers SFINAE.
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