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

时间:2018-08-22 08:15:19

标签: 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;
}

即使有更好的方法来解决我的问题,我也很想理解为什么在介绍的示例中enable_if如此工作(而不是这样)。

1 个答案:

答案 0 :(得分:5)

#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();

对于#4,默认模板值/类型不属于签名的一部分,因此一旦删除,您就拥有了

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

具有几种定义的相同方法:破坏ODR。

对于#3,它将是:

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

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

不同。