简体   繁体   English

`static constexpr` function 在常量表达式中调用是...错误?

[英]`static constexpr` function called in a constant expression is...an error?

I have the following code:我有以下代码:

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

I would expect that since foo() is a static constexpr function, and since it's defined before bar is declared, this would be perfectly acceptable.我希望由于foo()static constexpr function,并且由于它是在声明bar之前定义的,因此这是完全可以接受的。

However, g++ gives me the following error:但是, g++给了我以下错误:

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

This is...less than helpful, since the ability to call a function in a constant expression is the entire point of constexpr .这......没有什么帮助,因为在常量表达式中调用 function 的能力是constexpr的全部要点

clang++ is a little more helpful. clang++更有帮助。 In addition to an error message stating that the argument to noexcept must be a constant expression, it says:除了指出noexcept的参数必须是常量表达式的错误消息外,它还说:

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

So...is this a two-pass-compilation problem?那么......这是一个两遍编译问题吗? Is the issue that the compiler is attempting to declare all the member functions in the class before any of them are defined?问题是编译器试图在定义 class 之前声明所有成员函数吗? (Note that outside of the context of a class, neither compiler throws an error.) This surprises me; (请注意,在 class 的上下文之外,两个编译器都不会抛出错误。)这让我感到惊讶。 intuitively, I don't see any reason for static constexpr member functions not to be useable in any and all constant expressions, inside the class or out.直观地说,我看不出static constexpr成员函数不能在 class 内部或外部的任何和所有常量表达式中使用的任何理由。

As TC demonstrated with some links in a comment, the standard is not quite clear on this;正如 TC 在评论中通过一些链接所展示的那样,标准对此并不十分清楚; a similar problem arises with trailing return types using decltype(memberfunction()) .使用decltype(memberfunction())尾随返回类型decltype(memberfunction())出现类似的问题。

The central problem is that class members are generally not considered to be declared until after the class in which they're declared is complete.核心问题是类成员通常在声明它们的类完成之后才被认为是声明的。 Thus, regardless of the fact that foo is static constexpr and its declaration precedes that of bar , it cannot be considered "available" for use in a constant expression until MyClass is complete.因此,无论foostatic constexpr并且它的声明在bar之前,它都不能被视为“可用”用于常量表达式,直到MyClass完成。

As pointed out by Shafik Yaghmour , there is some attempt within the standard to avoid a dependency on the ordering of members within a class, and obviously allowing the example in the original question to compile would introduce an ordering dependency (since foo would need to be declared before bar ).正如Shafik Yaghmour 指出的那样,标准中有一些尝试避免依赖于类中成员的排序,并且显然允许原始问题中的示例编译会引入排序依赖(因为foo需要是在bar之前声明)。 However, there is already a minor dependency on ordering, because although constexpr functions can't be called inside noexcept , a noexcept expression itself might depend on an earlier declaration inside the class:然而,已经存在对排序的轻微依赖,因为虽然不能在noexcept内部调用constexpr函数,但noexcept表达式本身可能依赖于类内部的早期声明:

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

(Note that this is not actually a violation of 3.3.7, since there is still only one correct program that is possible here.) (请注意,这实际上并不违反 3.3.7,因为这里仍然只有一个正确的程序是可能的。)

This behavior may actually be a violation of the standard;这种行为实际上可能是违反标准的; TC points out (in a comment below) that foo here should actually be looked up in the scope of the whole class. TC 指出(在下面的评论中)实际上应该在整个类的范围内查找此处的foo Both g++ 4.9.2 and clang++ 3.5.1 fail with an error when bar is declared first but compile with no errors or warnings when foo is declared first.当首先声明bar时,g++ 4.9.2 和 clang++ 3.5.1 都失败并出现错误,但在首先声明foo时编译时没有错误或警告。 EDIT: clang++ trunk-revision 238946 (from shortly before the release of 3.7.0) does not fail when bar is declared first;编辑: clang++ trunk-revision 238946(在 3.7.0 发布前不久)在bar首先声明时不会失败; g++ 5.1 still fails. g++ 5.1 仍然失败。

Intriguingly, the following variation causes a "different exception specifier" with clang++ but not with g++:有趣的是,以下变体会导致使用 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())) { }

According to the error, the noexcept specification for the declaration of bar2 evaluates to noexcept(false) , which is then considered a mismatch for noexcept(noexcept(MyClasss::foo2())) .根据错误, noexcept声明bar2评估为noexcept(false) ,然后将其视为与noexcept(noexcept(MyClasss::foo2()))的不匹配。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 constexpr - 函数不能用于常量表达式 - constexpr - function cannot be used in a constant expression 什么决定了 constexpr function 是否是常量表达式? - What determines whether a constexpr function is a constant expression? 静态constexpr char m_pszFoo [] =“ *** FOO ***”具有编译错误表达式,未求值常量 - static constexpr char m_pszFoo[] = “***FOO***” has compile error expression did not evaluate constant 返回常量表达式不需要constexpr函数吗? - A constexpr function is not required to return a constant expression? g ++抱怨constexpr函数不是常量表达式 - g++ complains constexpr function is not a constant expression 错误! constexpr 变量必须由常量表达式 constexpr 初始化 - Error! constexpr variable must be initialized by a constant expression constexpr 如果函数名为constexpr,则条件为static_assert - Conditionally static_assert if function is called constexpr 为什么在调用此constexpr静态成员函数时不将其视为constexpr? - Why is this constexpr static member function not seen as constexpr when called? static_casting的结果是constexpr void *一个常量表达式吗? - Is the result of static_casting a constexpr void* a constant expression? 重复调用的函数中的静态常量与常量 - Static constant versus constant in a function that is called repeatedly
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM