作为 T.C.通过评论中的一些链接进行了演示,标准不是quite明确这一点;使用尾随返回类型也会出现类似的问题decltype(memberfunction())
.
核心问题是,类成员通常在声明它们的类完成之后才被视为已声明。因此,无论事实如何foo
is static constexpr
并且它的声明先于bar
,它不能被视为“可用”用于常量表达式,直到MyClass
做完了。
As 沙菲克·亚格莫尔指出 https://stackoverflow.com/q/26761385/1858225,标准中尝试避免对类中成员的排序的依赖,并且显然允许原始问题中的示例进行编译会引入排序依赖(因为foo
需要在之前声明bar
)。然而,有already对排序的依赖性较小,因为虽然constexpr
函数不能是called inside noexcept
, a noexcept
表达itself可能取决于类内较早的声明:
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,因为仍然只有one此处可能存在正确的程序。)
这种行为实际上可能是违反标准的; T.C.指出(在下面的评论中)foo
这里其实应该在全班范围内查找。 g++ 4.9.2 和 clang++ 3.5.1 都会失败并出现错误bar
首先声明,但编译时没有错误或警告foo
首先声明。EDIT:clang++ trunk-revision 238946(从 3.7.0 发布前不久开始)确实not失败时bar
首先声明; g++ 5.1 仍然失败。
有趣的是,以下变体会导致 clang++ 出现“不同的异常说明符”,但是not使用 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
规范为宣言 of bar2
评估为noexcept(false)
,然后被认为是不匹配的noexcept(noexcept(MyClasss::foo2()))
.