【问题标题】:Declaring a delegating method as constexpr whenever the invoked function is specified with constexpr每当使用 constexpr 指定调用的函数时,将委托方法声明为 constexpr
【发布时间】:2016-04-05 15:04:12
【问题描述】:

请考虑以下课程

template<class T>
class foo
{
public:
    auto bar() { return m_t.bar(); }

private:
    T m_t;
};

如果我们希望foo&lt;T&gt;::barT::bar 不抛出时不抛出,我们可以将其声明更改为

auto bar() noexcept(noexcept(m_t.bar())) { return m_t.bar(); }

但是,如果我们希望在 T::barconstexpr 一起指定时将 foo&lt;T&gt;::bar 指定为 constexpr,我们该怎么办?

我们可以写吗

constexpr auto bar() noexcept(noexcept(m_t.bar())) { return m_t.bar(); }

它在任何一种情况下都可以工作吗?我已经用 clang 3.7 (C++17) 对此进行了测试,似乎是这样,但我不确定编译器是否在这里正常工作。

【问题讨论】:

  • 请记住,constexpr 仍然只是一个提示,它可以在编译时进行评估,但并非必须如此。这允许您的方法签名适用于这两种情况,所以是的,这是有效的。

标签: c++ templates c++14 constexpr c++17


【解决方案1】:

来自[dcl.constexpr]

如果 constexpr 函数模板或类模板的成员函数的实例化模板特化无法满足 constexpr 函数或 constexpr 构造函数的要求,则该特化仍然是 constexpr 函数或constexpr 构造函数,即使对此类函数的调用不能出现在常量表达式中。如果模板的特殊化不能满足constexpr 函数或constexpr 构造函数的要求,当被视为非模板函数或构造函数时,则模板是非良构的;无需诊断。

鉴于有Ts 可以有一个constexpr X bar() 可以在常量表达式中使用,模板很好。如果T 有一个非constexpr bar(),那么foo::bar 仍被视为constexpr,但不能出现在常量表达式中。

【讨论】:

  • 你可以扩展这个答案,注意默认构造函数(可能还有其他特殊成员,没有检查)可以隐式为constexpr(如果它们的所有成员都是constexpr),然后关键字可以省略。此外,如果bar() 内部有任何禁止构造(gotonew 等),那么编译器将推断没有T 可以将bar 呈现为constexpr
  • @TemplateRex 这可能超出范围?我不希望答案只列出constexpr 的所有规则。 (是的,复制/移动构造/分配也是如此。)
  • 是的,可能超出范围。虽然我确实希望像constexpr(auto) :)
  • @TemplateRex 需要 moar auto :)
猜你喜欢
  • 1970-01-01
  • 2022-09-23
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-13
  • 1970-01-01
相关资源
最近更新 更多