если функция constexpr и требует выражения специального понятия, проверяя
Скажем, учитывая c++17 if constexpr
и понятия TS (например, в последних версиях gcc), мы хотели бы проверить, имеет ли тип в функции шаблона вложенный тип:
#include <iostream>
struct Foo { using Bar = int; };
template<typename T>
void doSmth(T)
{
if constexpr (requires { typename T::Bar; })
std::cout << "has nested! " << typename T::Bar {} << std::endl;
else
std::cout << "no nested!" << std::endl;
}
int main()
{
doSmth(Foo {});
//doSmth(0);
}
Документация по концепциям скудна, поэтому я, возможно, ошибся, но похоже, что это все (и живой пример находится на Wandbox).
Теперь давайте рассмотрим, что должно произойти при раскомментировании другого вызова doSmth
. Представляется разумным ожидать, что требование-клаузула будет оценивать false
, и будет взята ветвь else
if constexpr
. Вопреки этому, gcc делает эту трудную ошибку:
prog.cc: In instantiation of 'void doSmth(T) [with T = int]':
prog.cc:17:13: required from here
prog.cc:8:5: error: 'int' is not a class, struct, or union type
if constexpr (requires { typename T::Bar; })
^~
Это ошибка в gcc, или это предполагаемое поведение?
1 ответ:
Concepts issue 3 ("Allow requires-expression s in more contexts") получил статус WP в июне. И судя по нынешнему виду [expr.подтянутый.req] , в частности p6:
Замена аргументов шаблона вrequirements-выражение может привести к образованию недопустимых типов или выражений в его требованиях или нарушению семантических ограничений этих требований. В таких случаях требует-выражения вычисляется какfalse
; это не приводит к неправильному формированию программы.Я бы сказал, что ваш код в порядке, и GCC не реализовал решение проблемы 3 должным образом.