если функция 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 5

1 ответ:

Concepts issue 3 ("Allow requires-expression s in more contexts") получил статус WP в июне. И судя по нынешнему виду [expr.подтянутый.req] , в частности p6:

Замена аргументов шаблона вrequirements-выражение может привести к образованию недопустимых типов или выражений в его требованиях или нарушению семантических ограничений этих требований. В таких случаях требует-выражения вычисляется как false; это не приводит к неправильному формированию программы.

Я бы сказал, что ваш код в порядке, и GCC не реализовал решение проблемы 3 должным образом.