【问题标题】:Is gcc wrongly evaluating std::declval in this concept definition?gcc 在这个概念定义中是否错误地评估了 std::declval ?
【发布时间】:2019-09-13 23:07:54
【问题描述】:

在这个概念定义中:

#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 requires-expression 是 bool 类型的纯右值,其值如下所述。出现在需求主体中的表达式是未计算的操作数。

【问题讨论】:

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


    【解决方案1】:

    拒绝这个代码有错吗?

    是的,从不评估概念,正如您引用的引文所证明的那样。这是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

    【讨论】:

    • 感谢您对std::forward的需求的评论。
    猜你喜欢
    • 2019-04-15
    • 2022-11-19
    • 1970-01-01
    • 1970-01-01
    • 2018-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多