gcc是否在此概念定义中错误地评估了std :: declval?

时间:2019-04-24 15:27:28

标签: 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   require-expression是bool类型的prvalue,其值如下所述。在需求主体中出现的表达式是未评估的操作数。

1 个答案:

答案 0 :(得分:12)

  

拒绝此代码是否有误?

是的,从不引用任何概念,正如您所引用的报价所证明的那样。这是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