gcc 是否在这个概念定义中错误地评估 std::declval ?
Is gcc wrongly evaluating std::declval in this concept definition?
在这个概念定义中:
#include <utility>
template<class Func, class Ret, class... Args>
concept Invokable = requires(Func f) {
{ f(std::declval<Args>()...) } -> Ret;
};
像这样实例化时:
static_assert(Invokable<decltype([](int){}), void, int>);
gcc-9.0.1(主干)转储(好吧,准确地说是标准库实现):
$ g++ -O2 -std=c++2a -fconcepts -Wall -Wextra -Werror -c tu1.cpp
error: static assertion failed: declval() must not be used!
2204 | static_assert(__declval_protector<_Tp>::__stop,
| ^~~~~~
演示:https://godbolt.org/z/D0ygU4
拒绝此代码是否错误?如果不是,我做错了什么?如果是,应该在哪里报告此错误?
备注
已接受
template<auto f, class... Args>
constexpr auto size_of_return_type = sizeof(f(std::declval<Args>()...));
像这样实例化时:
static_assert(sizeof(int) == size_of_return_type<[](int){ return 0; }, int>);
演示:https://godbolt.org/z/gYGk8U
最新的 C++2a 草案状态:
[expr.prim.req]/2
A requires-expression is a prvalue of type bool whose value is described below. Expressions appearing within a requirement-body are unevaluated operands.
Is it wrong to reject this code?
是的,从不评估概念,正如您引用的引文所证明的那样。这是gcc bug 68781 and gcc bug 82171.
请注意,没有理由在概念中使用 declval
。这个更直接:
template<class Func, class Ret, class... Args>
concept InvokableR = requires(Func&& f, Args&&... args) {
{ f(std::forward<Args>(args)...) } -> Ret;
};
declval
存在是因为您需要某种类型的表达式,而您不能只写 T()
因为这需要默认构造函数。概念为您提供了作为第一个 class 语言功能的能力。不过仍然需要 forward
。
在这个概念定义中:
#include <utility>
template<class Func, class Ret, class... Args>
concept Invokable = requires(Func f) {
{ f(std::declval<Args>()...) } -> Ret;
};
像这样实例化时:
static_assert(Invokable<decltype([](int){}), void, int>);
gcc-9.0.1(主干)转储(好吧,准确地说是标准库实现):
$ g++ -O2 -std=c++2a -fconcepts -Wall -Wextra -Werror -c tu1.cpp error: static assertion failed: declval() must not be used! 2204 | static_assert(__declval_protector<_Tp>::__stop, | ^~~~~~
演示:https://godbolt.org/z/D0ygU4
拒绝此代码是否错误?如果不是,我做错了什么?如果是,应该在哪里报告此错误?
备注
已接受
template<auto f, class... Args>
constexpr auto size_of_return_type = sizeof(f(std::declval<Args>()...));
像这样实例化时:
static_assert(sizeof(int) == size_of_return_type<[](int){ return 0; }, int>);
演示:https://godbolt.org/z/gYGk8U
最新的 C++2a 草案状态:
[expr.prim.req]/2
A requires-expression is a prvalue of type bool whose value is described below. Expressions appearing within a requirement-body are unevaluated operands.
Is it wrong to reject this code?
是的,从不评估概念,正如您引用的引文所证明的那样。这是gcc bug 68781 and gcc bug 82171.
请注意,没有理由在概念中使用 declval
。这个更直接:
template<class Func, class Ret, class... Args>
concept InvokableR = requires(Func&& f, Args&&... args) {
{ f(std::forward<Args>(args)...) } -> Ret;
};
declval
存在是因为您需要某种类型的表达式,而您不能只写 T()
因为这需要默认构造函数。概念为您提供了作为第一个 class 语言功能的能力。不过仍然需要 forward
。