【问题标题】:Using enable_if to prevent declaration? [duplicate]使用 enable_if 来阻止声明? [复制]
【发布时间】:2020-11-15 13:48:32
【问题描述】:

Stroustrup C++ 第 4 版第 796 页指出“如果 Enable_if 的条件评估为假,则它所在的整个函数声明将被完全忽略。”和“......我们没有声明任何东西。”。

有谁知道为什么要声明第一个f0()?我是否正确使用了enable_if

我的目标是禁用其中一个声明。我不确定f0() 是如何具有返回类型的,因为false 版本应该缺少::type

#include <type_traits>
using namespace std;

template<bool B, typename T>
using Enable_if = typename std::enable_if<B,T>::type;

template <class T>
class X {
    Enable_if<false, T> f0(int x) {};
    Enable_if<true, T> f0(int x) {};
};

int main(void)
{
    X<void> xx;
    return 0;
}

编译:

clang++ -std=c++11 -Wall -pedantic test197.cc && ./a.out
test197.cc:10:24: error: functions that differ only in their return type cannot
      be overloaded
    Enable_if<true, T> f0(int x) {};
    ~~~~~~~~~~~~~~~~~~ ^
test197.cc:9:25: note: previous definition is here
    Enable_if<false, T> f0(int x) {};
    ~~~~~~~~~~~~~~~~~~~ ^
1 error generated.

【问题讨论】:

  • SFINAE 通常要求相关声明是模板本身。在这种情况下,f0 重载都不是模板;他们是模板类型的成员是不够的。

标签: c++ templates sfinae enable-if


【解决方案1】:

你不能使用这种方式,因为你的对象在任何情况下都会被创建,因为类没有创建或不创建的条件。然后这里Enable_if&lt;false, T&gt; f0(int x) {};,条件是false那么就没有类型了。请注意,模板类是在开头传递参数时实例化的,所做的只是将T 替换为void

您可以使用的一种方法如下

#include <type_traits>
using namespace std;

template<bool B, typename T>
using Enable_if = typename std::enable_if<B,T>::type;


struct X {
    template <class T>
    Enable_if<true, T> f0(int x) {}
    template <class T>
    Enable_if<false, T> f0(int x) {}
};

int main(void)
{
    X xx;
    xx.f0<void>(4);
    return 0;
}

这里我们有两个函数模板,因此它们中的每一个都可能被实例化或不被实例化,这取决于类内部的条件。如果为真,该函数将被实例化,反之亦然。注意这里只实例化了需要的函数。

【讨论】:

  • 这清除了用法。我试图了解错误案例如何阻止声明以及为什么需要模板参数。我认为 SFINAE 只发生在类参数中,所以不确定这里是否发生了这种情况。你知道吗?
  • @JeJe 你能改写你的最后一句话吗?没看懂。
  • @JeJo 我引用了这个帖子中发布的答案。我理解 SFINAE 仅在模板参数的参数推导中的替换使构造格式不正确时才有效。例如,在这种情况下,您声明 template &lt;typename enable_if&lt;false&gt;::value* = nullptr&gt; void f0() {}。在此线程的上述示例中,我看不到“模板参数的参数推导中的替换”发生在哪里。那是我的困惑,副本没有回答这个问题
  • 总结一下,这个线程中asmmo的例子中哪个模板参数替换失败了?如果T没有推导出返回类型,这怎么可能?
  • @notarob 如果失败,寺庙将根本不会被实例化,因此没有替代。
猜你喜欢
  • 2016-03-13
  • 2020-11-15
  • 1970-01-01
  • 2011-10-12
  • 2021-02-18
  • 1970-01-01
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
相关资源
最近更新 更多