Концепция в заголовке не ограничивает пакет параметров в C ++ 20? - PullRequest
3 голосов
/ 03 мая 2020

Контекст: я переписываю библиотеку, которая работала с G CC -fconcepts, на C ++ 20. Clang 10 и G CC 10 вызывают у меня ту же неожиданную проблему, так что, вероятно, это моя ошибка.

У меня есть шаблон класса, который поддерживает два случая. Он может быть создан либо из списка pin_out, либо из списка port_out.

template< typename T > concept pin_out = T::is_pin_out;

template< typename... Ts > concept pin_out_list = ( pin_out< Ts > && ... );

template< typename T > concept port_out = T::is_port_out;

template< typename... Ts >
   requires pin_out_list< Ts...> || ( port_out< Ts > && ... )
struct port;

Когда я пишу специализацию для списка pins_out с концепциями TS, я могу написать

template< pin_out_list... Ts > 
struct port< Ts... > {};

но теперь с C ++ 20 компиляторы жалуются, что специализация не более ограничена, чем базовая. Когда я добавляю условие require, оно компилируется.

template< pin_out_list... Ts > 
   requires pin_out_list< Ts... >
struct port< Ts... > {};

И я могу удалить pin_out_list ... из заголовка шаблона.

template< typename... Ts > 
   requires pin_out_list< Ts... >
struct port< Ts... > {};

Является ли pin_out_list ... в специализация теперь молча игнорируется?

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

1 Ответ

3 голосов
/ 03 мая 2020

Одна из многих вещей, которые P1141 изменились, заключалась в том, что фактически означает ограничение c:

В [temp.param] / 11 мы имеем:

template <C2... T> struct s3; // associates C2<T...>

Это, кажется, делает неожиданную вещь, к которой одновременно применяются ограничения для более чем одного типа в пачке.

И в результате этой статьи ограничение variadi c теперь применяется ко всем типам на обороте. То есть теперь у нас есть (это в [temp.param] / 5 сейчас):

template <C2... T> struct s3; // associates (C2<T> && ... )

В результате эта специализация:

template< pin_out_list... Ts > 
struct port< Ts... > {};

означает:

template <typename... Ts> requires (pin_out_list<Ts> && ...)
struct port<Ts...>;

, а не:

template <typename... Ts> requires pin_out_list<Ts...>
struct port<Ts...>;

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

...