如果调用的函数已被声明为constexpr,那么将委托方法声明为constexpr

4
请考虑以下类:
template<class T>
class foo
{
public:
    auto bar() { return m_t.bar(); }

private:
    T m_t;
};

如果我们希望foo<T>::barT::bar不抛出异常时也不会抛出异常,我们可以改变它的声明为

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

但是,如果我们希望foo<T>::barT::bar指定为constexpr时也被指定为constexpr,我们该怎么办呢?

我们可以这样写:

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

那么它将适用于任何情况吗?我已经使用clang 3.7(C++17)进行了测试,似乎是这种情况,但我不确定编译器是否在此处正常工作。


请记住,constexpr仍然只是一个提示,它可以在编译时进行评估,但不一定要这样做。这使得您的方法签名适用于两种情况,因此,是的,这是有效的。 - Hatted Rooster
1个回答

5

来自[dcl.constexpr]

如果一个constexpr函数模板或类模板的成员函数的实例化模板特化不满足constexpr函数或constexpr构造函数的要求,那么该特化仍然是一个constexpr函数或constexpr构造函数,尽管调用这样的函数不能出现在常量表达式中。如果当作非模板函数或构造函数考虑时,模板的任何特化都不满足constexpr函数或constexpr构造函数的要求,则该模板是有错误的,无需诊断。

假设存在可以在常量表达式中使用的T类型的constexpr X bar(),则该模板是正确的。如果T有一个非constexprbar(),则foo::bar仍被认为是constexpr,但只是不能出现在常量表达式中。


你可以进一步说明默认构造函数(也许是其他特殊成员,没有检查)可以隐式地被定义为constexpr(如果它们的所有成员都是constexpr),那么关键字就可以省略。此外,如果bar()中存在任何禁止使用的结构(如gotonew等),编译器将推断出没有任何T能使得barconstexpr - TemplateRex
@TemplateRex 这可能超出了范围?我不希望答案仅列出所有constexpr规则的列表。(是的,复制/移动构造/赋值也是如此。) - Barry
是的,可能超出范围了。虽然我希望有类似于 constexpr(auto) 的东西 :) - TemplateRex
@TemplateRex 需要更多的自动化 :) - Barry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接