c++ - gcc 在这个概念定义中错误地评估了 std::declval 吗?

标签 c++ g++ c++-concepts c++20

在这个概念定义中:

#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 68781gcc 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() 因为这需要默认构造函数。概念为您提供了作为一流语言功能的能力。不过仍然需要 forward

关于c++ - gcc 在这个概念定义中错误地评估了 std::declval 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55833660/

相关文章:

c++ - 避免在模板的前向声明中出现重复的 require 子句?

c++ - MSVC 中的模板静态定义和显式特化实例化错误

c++ - concepts(C++20) 可以用作 bool 值吗?

c++ - 如何避免与 VSConstants.S_OK 字段命名冲突?

C++11 初始化列表 + 函数指针让我头疼

c++ - g++ 链接目标文件无法链接

尝试从使用 makefile 生成的目标文件构建时出现 C++ 链接器错误。当我刚刚构建它时不会发生

c++ - 如何为不可创建类创建包装器?

c++ - Visual C++ 2010 控制台应用程序 dwFontSize 值?

c++ - min 的最佳实现是什么?