【问题标题】:std::enable_if for two different methods implementation (4 different cases)std::enable_if 用于两种不同的方法实现(4 种不同的情况)
【发布时间】:2018-08-22 08:15:18
【问题描述】:

我需要为 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 像它一样(而不是)在给出的示例中起作用。

【问题讨论】:

标签: c++ templates


【解决方案1】:

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

这是不同的。

【讨论】:

  • 也许在#3 处很有趣,可以更清楚地说明差异:if 第二个foo is 启用,它将到达&lt;typename B, void*&gt;
  • @Aconcagua: 但是签名 differs 在替换之前,例如 Demo 会产生模棱两可的调用(而不是违反 ODR,正如你的句子所暗示的那样)。
  • 不明白为什么我的评论会暗示违反 ODR,我的意图 使不同的签名更加明显......
  • 我的意思是typename &lt;typename T, std::enable_if_t&lt;cond&lt;T&gt;, int&gt;&gt; voif f()template &lt;typename T, int&gt; void f()是2个不同的签名,即使替换后,它们的结果是一样的。
  • 啊,我明白了...被您的强调误导了(“但签名甚至在之前替换之前也不同”会更明显),但有趣的方面...
猜你喜欢
  • 1970-01-01
  • 2018-10-03
  • 2017-04-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 1970-01-01
相关资源
最近更新 更多