永远不会计算为常量表达式的 lambda() 可以是 C++ 中的“constexpr”函数吗?
Can lambda() that never evaluates to a constant expression be a `constexpr`-function in C++?
Lambda 的 operator()
根据 https://en.cppreference.com/w/cpp/language/lambda
隐式 constexpr
When this specifier (constexpr
) is not present, the function call operator or any given operator template specialization will be constexpr
anyway, if it happens to satisfy all constexpr
function requirements
并且根据 https://en.cppreference.com/w/cpp/language/constexpr
对 constexpr
函数的要求
there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.
在下一个例子中,函数 t()
总是通过调用 lambda l()
:
抛出异常
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
GCC 拒绝此函数并出现错误:
call to non-'constexpr' function '<lambda()>'
但是 Clang 接受了这个程序(直到函数 t()
被用在一个不断的求值中),这意味着它认为 l()
是一个 constexpr
-函数,demo: https://gcc.godbolt.org/z/j1z7ee3Wv
这是 Clang 中的错误,还是这样的编译器行为也可以接受?
当您实际尝试在需要常量表达式的上下文中使用 t()
的结果时,所有三个编译器都会发出错误。 For example:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
template <bool x>
struct dummy {};
int main() {
dummy< t() > d; // error: t() is not a constant expression
}
正如 NathanOliver 在评论中提到的那样,您的引述已经指出:
[...] No diagnostic is required for a violation of this bullet.
编译器不一定需要证明没有一组参数值允许函数 return 常量表达式。另一方面,编译器可以很容易地验证给定的参数值,结果不是常量表达式。
Lambda 的 operator()
根据 https://en.cppreference.com/w/cpp/language/lambda
constexpr
When this specifier (
constexpr
) is not present, the function call operator or any given operator template specialization will beconstexpr
anyway, if it happens to satisfy allconstexpr
function requirements
并且根据 https://en.cppreference.com/w/cpp/language/constexpr
对constexpr
函数的要求
there exists at least one set of argument values such that an invocation of the function could be an evaluated subexpression of a core constant expression (for constructors, use in a constant initializer is sufficient) (since C++14). No diagnostic is required for a violation of this bullet.
在下一个例子中,函数 t()
总是通过调用 lambda l()
:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
GCC 拒绝此函数并出现错误:
call to non-'constexpr' function '<lambda()>'
但是 Clang 接受了这个程序(直到函数 t()
被用在一个不断的求值中),这意味着它认为 l()
是一个 constexpr
-函数,demo: https://gcc.godbolt.org/z/j1z7ee3Wv
这是 Clang 中的错误,还是这样的编译器行为也可以接受?
当您实际尝试在需要常量表达式的上下文中使用 t()
的结果时,所有三个编译器都会发出错误。 For example:
auto l = []()->bool { throw 42; };
constexpr bool t() { return l(); }
template <bool x>
struct dummy {};
int main() {
dummy< t() > d; // error: t() is not a constant expression
}
正如 NathanOliver 在评论中提到的那样,您的引述已经指出:
[...] No diagnostic is required for a violation of this bullet.
编译器不一定需要证明没有一组参数值允许函数 return 常量表达式。另一方面,编译器可以很容易地验证给定的参数值,结果不是常量表达式。