问题
I need to implement two different methods for const and non-const types. I have manage to write working code but I do not understand why some of its flavors are OK and some of them are not.
Here is simplified example and I would like to know why #1 works but #2 is not, and same regarding #3 vs #4:
#include <iostream>
#include <vector>
template <typename T>
class X {
public:
// #1 - works
template<typename B = T, typename std::enable_if<std::is_const<B>::value, int>::type = 0>
void foo() {std::cout << "CONST" << std::endl;}
template<typename B = T, typename std::enable_if<std::is_const<B>::value == false, int>::type = 0>
void foo() {std::cout << "NON-CONST" << std::endl;}
// #2 - does not work "no type named 'type' in 'std::__1::enable_if<false, int>'; 'enable_if' cannot be used to disable this declaration"
// template<typename std::enable_if<std::is_const<T>::value, int>::type = 0>
// void foo() {std::cout << "CONST" << std::endl;}
// template<typename std::enable_if<std::is_const<T>::value == false, int>::type = 0>
// void foo() {std::cout << "NON-CONST" << std::endl;}
// #3 - works
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value>::type>
// void foo() {std::cout << "CONST" << std::endl;}
// template<typename B = T, typename std::enable_if<std::is_const<B>::value == false>::type * = nullptr>
// void foo() {std::cout << "NON-CONST" << std::endl;}
// # 4 - does not work - "class member cannot be redeclared"
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value>::type>
// void foo() {std::cout << "CONST" << std::endl;}
// template<typename B = T, typename = typename std::enable_if<std::is_const<B>::value == false>::type>
// void foo() {std::cout << "NON-CONST" << std::endl;}
};
int main() {
X<int> v;
X<const int> vConst;
v.foo();
vConst.foo();
return 0;
}
Even if there is a better approach to solve my problem I would really like to understand why enable_if works like it (not) works in presented examples.
回答1:
#2
doesn't works as your have hard failure as T
is fixed by the class.
so you really have
template<typename std::enable_if<true, int>::type = 0> // -> template<int = 0> void foo();
void foo();
template<typename std::enable_if<false, int>::type = 0> // Hard error failure
void foo();
For #4
, default template value/type are not part of the signature, so once those removed, you have
template <typename B, typename> void foo() {std::cout << "CONST" << std::endl;}
template <typename B, typename> void foo() {std::cout << "NON-CONST" << std::endl;}
Same method with several definitions: you break ODR.
For #3
, it would be:
template<typename B, typename>
void foo();
template<typename B, typename std::enable_if<std::is_const<B>::value == false>::type *>
void foo();
which are different.
来源:https://stackoverflow.com/questions/51962542/stdenable-if-for-two-different-methods-implementation-4-different-cases