在常量表达式中调用的 `static constexpr` 函数是……一个错误?
`static constexpr` function called in a constant expression is...an error?
我有以下代码:
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
.[=21= 的全部要点]
clang++
更有帮助。除了指出 noexcept
的参数必须是常量表达式的错误消息外,它还表示:
note: undefined function 'foo' cannot be used in a constant expression
note: declared here
static constexpr bool foo() { return true; }
^
所以...这是一个二次编译问题吗?问题是编译器在定义 class 之前试图声明所有成员函数吗? (请注意,在 class 的上下文之外,编译器都不会抛出错误。)这让我感到惊讶;直觉上,我看不出任何 static constexpr
成员函数不能用于 class 内部或外部的任何和所有常量表达式的原因。
为T.C。在评论中用一些链接进行了演示,标准对此 相当 不清楚;使用 decltype(memberfunction())
.
的尾随 return 类型会出现类似的问题
主要问题是 class 成员通常在声明它们的 class 完成后才被视为已声明。因此,不管 foo
是 static constexpr
并且它的声明先于 bar
,它不能被认为是 "available" 用于常量表达式,直到 MyClass
完成。
作为 pointed out by Shafik Yaghmour,标准中有一些尝试避免依赖 class 中成员的顺序,显然允许编译原始问题中的示例会引入一个顺序依赖(因为 foo
需要在 bar
之前声明)。但是,已经对顺序有轻微的依赖性,因为虽然 constexpr
函数不能在 noexcept
中被 调用 , noexcept
表达式 本身 可能依赖于 class:
中的早期声明
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
时,编译时没有错误或警告。 编辑: clang++ trunk-revision 238946(从 3.7.0 发布前不久开始)在首先声明 bar
时 not 失败; g++ 5.1 仍然失败。
有趣的是,以下变体导致 "different exception specifier" with clang++ 但 not with 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())) { }
根据错误,bar2
的 声明 的 noexcept
规范评估为 noexcept(false)
,然后被认为是不匹配noexcept(noexcept(MyClasss::foo2()))
.
我有以下代码:
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
.[=21= 的全部要点]
clang++
更有帮助。除了指出 noexcept
的参数必须是常量表达式的错误消息外,它还表示:
note: undefined function 'foo' cannot be used in a constant expression
note: declared here
static constexpr bool foo() { return true; }
^
所以...这是一个二次编译问题吗?问题是编译器在定义 class 之前试图声明所有成员函数吗? (请注意,在 class 的上下文之外,编译器都不会抛出错误。)这让我感到惊讶;直觉上,我看不出任何 static constexpr
成员函数不能用于 class 内部或外部的任何和所有常量表达式的原因。
为T.C。在评论中用一些链接进行了演示,标准对此 相当 不清楚;使用 decltype(memberfunction())
.
主要问题是 class 成员通常在声明它们的 class 完成后才被视为已声明。因此,不管 foo
是 static constexpr
并且它的声明先于 bar
,它不能被认为是 "available" 用于常量表达式,直到 MyClass
完成。
作为 pointed out by Shafik Yaghmour,标准中有一些尝试避免依赖 class 中成员的顺序,显然允许编译原始问题中的示例会引入一个顺序依赖(因为 foo
需要在 bar
之前声明)。但是,已经对顺序有轻微的依赖性,因为虽然 constexpr
函数不能在 noexcept
中被 调用 , noexcept
表达式 本身 可能依赖于 class:
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
时,编译时没有错误或警告。 编辑: clang++ trunk-revision 238946(从 3.7.0 发布前不久开始)在首先声明 bar
时 not 失败; g++ 5.1 仍然失败。
有趣的是,以下变体导致 "different exception specifier" with clang++ 但 not with 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())) { }
根据错误,bar2
的 声明 的 noexcept
规范评估为 noexcept(false)
,然后被认为是不匹配noexcept(noexcept(MyClasss::foo2()))
.