c++ - `static constexpr` 在常量表达式中调用的函数是...错误?

标签 c++ c++11 constexpr noexcept constant-expression

我有以下代码:

class MyClass
{
  static constexpr bool foo() { return true; }
  void bar() noexcept(foo()) { }    
};

我希望因为 foo() 是一个 static constexpr 函数,并且由于它是在声明 bar 之前定义的,所以这将是完全可以接受。

但是,g++ 给了我以下错误:

 error: ‘static constexpr bool MyClass::foo()’ called in a constant expression

这...没什么用,因为在常量表达式中调用函数的能力是constexpr的全部要点。

clang++ 更有帮助。除了指出 noexcept 的参数必须是常量表达式的错误消息外,它还显示:

note: undefined function 'foo' cannot be used in a constant expression
note: declared here
static constexpr bool foo() { return true; }
                      ^

那么...这是一个两遍编译问题吗?编译器是否试图在定义类中的所有成员函数之前声明它们的问题? (请注意,在类的上下文之外,编译器都不会抛出错误。)这让我感到惊讶;直观地说,我看不出有任何理由让 static constexpr 成员函数不能在类内或类外的任何和所有常量表达式中使用。

最佳答案

作为 T.C.通过评论中的一些链接进行演示,标准对此并不相当明确;使用 decltype(memberfunction()) 的尾随返回类型也会出现类似的问题。

核心问题是,在声明它们的类完成之前,通常不会考虑声明类成员。因此,不管 foostatic constexpr 并且它的声明先于 bar 的事实,在 MyClass 完成之前,它不能被认为是“可用的”用于常量表达式。

作为 pointed out by Shafik Yaghmour ,标准中有一些尝试避免依赖于类中成员的顺序,并且显然允许编译原始问题中的示例将引入顺序依赖(因为需要声明 foobar 之前)。但是,已经对排序有一点依赖性,因为虽然 constexpr 函数不能在 noexcept调用,但 noexcept 表达式本身可能取决于在类内的较早声明上:

class MyClass
{
    // void bar() noexcept(noexcept(foo())); // ERROR if declared here
    static constexpr bool foo();
    void bar() noexcept(noexcept(foo())); // NO ERROR
}

(请注意,这实际上并不违反 3.3.7,因为这里仍然只有 一个 正确的程序是可能的。)

这种行为实际上可能是违反标准的; T.C.指出(在下面的评论中)这里的 foo 实际上应该在整个类(class)的范围内查找。当首先声明 bar 时,g++ 4.9.2 和 clang++ 3.5.1 都失败并出现错误,但在首先声明 foo 时编译时没有错误或警告。 编辑:当首先声明 bar 时,clang++ trunk-revision 238946(来自 3.7.0 发布前不久)不会失败; g++ 5.1 仍然失败。

有趣的是,以下变化会导致 clang++ 出现“不同的异常说明符”,而 g++ 则不会:

class MyClass
{
  static constexpr bool foo2();
  void bar2() noexcept(noexcept(foo2()));
};

constexpr bool MyClass::foo2() { return true; }
void MyClass::bar2() noexcept(noexcept(MyClass::foo2())) { }

根据错误,noexcept声明bar2 规范计算为 noexcept(false) ,然后将其视为与 noexcept(noexcept(MyClasss::foo2())) 不匹配。

关于c++ - `static constexpr` 在常量表达式中调用的函数是...错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29551223/

相关文章:

c++ - 调用C标准库函数的标准C++方式

c++ - 如何从map<pair<string, int>,pair<string, Array>>中迭代查找?

c++ - 如何在Debian系统中将matlab编译的代码集成到c++中

c++ - 函数返回数组但输出不符合预期

c++ - 来自 ShellExecuteEx 的意外/不一致行为

vim - 如何向 syntastic vim 插件添加 c++11 支持?

c++ - Variadic constexpr 类型选择器

c++ - 如何定义一个 constexpr 构造数组,该数组在多个翻译单元上只有一个实例?

c++ - 如何以 constexpr 方式调用具有元组输入的模板化静态类方法

c++ - 套接字内存泄漏