【问题标题】:c++ std::enable_ifc++ std::enable_if
【发布时间】:2012-10-26 23:16:11
【问题描述】:

我对 std::enable_if 很陌生,想知道如何使用它。 我有一个模板类:

template<int a, int b>
class foo {
}

现在我只想在 a + b 等于 10 时实例化它。 我可以使用 std::enable_if 来实现吗?

第二个问题: 如果我在 foo 类中有成员

template<int a, int b>
class foo {
  int c;
}

我只想有c的时候

a = 5. 

如何使用 std::enable_if 做到这一点? 这是使用 std::enable_if 的正确案例吗?

【问题讨论】:

  • 这不是enable_if 的用途。它仅适用于 function 模板中的 deduced 类型。
  • @KerrekSB:或者禁用类模板的特化。长期以来,两者都是boost::enable_if 的核心用法,并且仍然是有效的用例。请注意,这通常是在基础模板的多个专业化的上下文中完成的,以选择一个而不是其他模板,而不是完全禁用一个模板。
  • @DavidRodríguez-dribeas:这是一个很好的观点。到目前为止,我还没有将它用于类模板专业化......
  • 更简单:template&lt;int a&gt; class foo { static const int b = 10 - a;

标签: c++ c++11


【解决方案1】:
template<int a, int b, typename T = typename std::enable_if<a + b == 10>::type>
class foo {
};

这应该可以完成工作;只需确保在实例化模板时从不显式提供第三个模板参数。


正如其他人提到的,static_assert 更合适。

【讨论】:

  • +1:虽然只强制一个特定的组合 static_assert 更好,但它更强大,因为它允许生成基础模板的多个特化并根据属性选择一个或另一个实例化论点
  • +1 教我可以在模板参数中使用算术和逻辑表达式
  • 好的,现在我改变了要求 :-) 如果我有会员怎么办\n
  • 如果我在类 foo: int c 中有一个成员并且我只想在模板参数 a 为 5 时拥有该成员怎么办?如何使用 std::enable_if 做到这一点? @Zoidberg
  • @WhatABeautifulWorld 你应该专门针对 5 的模板。所以你可能有 template &lt;int N&gt; struct foo { int a, b; }; template &lt;&gt; struct foo&lt;5&gt; { int a, b, c; };
【解决方案2】:

我猜你可以更好地使用 static_assert 而不是 enable_if 来强制执行该约束

template<int a, int b>
class foo {
    static_assert(a+b==10, "a+b is not 10");
};

int main()
{
    foo<5,5> f; // will compile
    foo<1,5> f; // will fail to compile with error: a+b is not 10
    return 0;
}

enable_if 主要用于根据类型特征有条件地从重载决议中删除函数和类,并为不同的类型特征提供单独的函数重载和特化。

【讨论】:

  • 我会选择这个解决方案而不是基于 std::enable_if 的解决方案,以便让我的图书馆的用户免于头痛。
  • 是的,我只是想学习如何使用 enable_if。但这可能是一个非常糟糕的例子:)
【解决方案3】:

使用 C++20

您只需在模板中添加 requires 即可实现:

template<int a, int b> requires (a + b == 10)
struct foo {
    int c;
};

int main() {
    foo<3, 7> ok;
    // foo<3, 8> doesnt_compile;
}

requires 子句得到一个 constant expression,其计算结果为 truefalse,从而决定是否将其视为正确匹配,如果 requires 子句为真,或忽略否则。

代码:https://godbolt.org/z/yHh4Et

【讨论】:

  • 许多人没有意识到一个简单的事实:static_assert 不限制类型,它限制实例化。可以使用 std 编译许多非法类型,例如using very_wrong = std::vector&lt;void ***&gt; 。 c++20 ad-hoc requires 非常优雅,而且是有原因的。
【解决方案4】:

简单,别用enable_if

template<bool Ten>
struct Base
{
    int c;
};

template<>
struct Base<false>
{ };

template<int a, int b>
struct foo : Base<a+b == 10>
{
};

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-08-29
  • 2013-06-03
  • 2016-02-25
  • 2014-03-27
  • 2016-12-19
  • 1970-01-01
  • 2021-03-07
相关资源
最近更新 更多