std :: enable_if用于两种不同的方法实现(4种不同的情况)

Krz*_*tof 2 c++ templates

我需要为const和非const类型实现两种不同的方法.我已经设法编写工作代码,但我不明白为什么它的一些味道是好的,而其中一些不是.

这是一个简化的例子,我想知道为什么#1有效,但#2不是,和#3对#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;
}
Run Code Online (Sandbox Code Playgroud)

即使有更好的方法来解决我的问题,我也很想理解为什么enable_if的工作原理(不是)在所提供的示例中有效.

Jar*_*d42 6

#2不适用,因为你已经T被班级修复了.

所以你真的有

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();
Run Code Online (Sandbox Code Playgroud)

因为#4,默认模板值/类型不是签名的一部分,所以一旦删除,你就有了

template <typename B, typename> void foo() {std::cout << "CONST" << std::endl;}
template <typename B, typename> void foo() {std::cout << "NON-CONST" << std::endl;}
Run Code Online (Sandbox Code Playgroud)

具有多个定义的相同方法:您打破ODR.

因为#3,它将是:

template<typename B, typename>
void foo();

template<typename B, typename std::enable_if<std::is_const<B>::value == false>::type *>
void foo();
Run Code Online (Sandbox Code Playgroud)

这是不同的.