Gcc неправильно оценивает std :: declval в этом определении понятия? - PullRequest
6 голосов
/ 24 апреля 2019

В этом определении понятия:

#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 - это значение типа bool, значение которого описано ниже. Выражения, появляющиеся в теле требования, являются неоцененными операндами.

1 Ответ

12 голосов
/ 24 апреля 2019

Неправильно ли отклонить этот код?

Да, понятия никогда не оцениваются, о чем свидетельствует цитируемая вами цитата.Это ошибка gcc 68781 и ошибка gcc 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 хотя.

...