Gcc неправильно оценивает std::declval в этом определении концепции?

#c #g #c -concepts #c 20

#c #g #c -концепции #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>);
  

Demo: https://godbolt.org/z/gYGk8U

Последние состояния проекта C 2a:

[expr.prim.req]/2 Требуемое выражение — это значение типа bool, значение которого описано ниже. Выражения, появляющиеся в теле требования, являются недооцененными операндами.

Ответ №1:

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

Да, концепции никогда не оцениваются, о чем свидетельствует цитируемая вами цитата. Это ошибка gcc 68781 и ошибка gcc 82171.

Обратите внимание, что нет причин использовать declval внутри концепций. Это более просто:

 template<class Func, class Ret, class... Args>
concept InvokableR = requires(Funcamp;amp; f, Argsamp;amp;... args) {
    { f(std::forward<Args>(args)...) } -> Ret;
};
  

declval существует, потому что вам нужно какое-то выражение определенного типа, и вы не можете просто написать T() , потому что для этого требуется конструктор по умолчанию. Концепции дают вам эту возможность в качестве первоклассной языковой функции. Все еще нужно forward , хотя.

Комментарии:

1. Спасибо за ваше замечание о необходимости std::forward .