Концепции великолепны, не поймите меня неправильно, но зачем нам для этого еще одно ключевое слово?
Рассмотрим следующий пример:
#include <type_traits>
template <typename T>
concept UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;
template <UnsignedConst T>
void foo(T bar);
С тем же успехом мы могли бы использовать следующий, на мой взгляд, более простой синтаксис:
/* ... */
template <typename T>
constexpr bool UnsignedConst = std::is_integral_v<T> && std::is_const_v<T>;
/* ... */
Под капотом концепции - это не что иное, как логические константы времени компиляции, зависящие от параметров шаблона (EDIT: НЕТ! См. принятый ответ). Даже requires
-предложения можно использовать с шаблонами переменных, поскольку они представляют собой просто выражения, которые оцениваются как логические значения во время компиляции.
🤔 А знаете ли вы, что...
C++ позволяет оптимизировать код на уровне компиляции для повышения производительности.
Под капотом концепции — это не что иное, как логические константы времени компиляции, зависящие от параметров шаблона.
Это неправда.
concept
обладает особыми свойствами, которых нет у простых constexpr bool
. В частности, concept
не может быть специализированным. Эта неспособность быть специализированным делает возможными правила подчинения понятий. Это позволяет стандарту устанавливать правила для того, что считается «более специализированной» версией шаблона.
Учитывая следующее:
template<typename T>
concept A = atomic_constraint_a<T>;
template<typename T>
concept B = atomic_constraint_a<T> && atomic_constraint_b<T>;
в рамках правил концепций C++ ясно, что A
включается в B
. Это означает, что любой тип T
, который удовлетворяет B
, обязательно удовлетворяет A
. Следовательно, если у вас есть два шаблона, один ограничен A
, а другой — B
, если вы передадите тип, удовлетворяющий B
, будет выбран именно тот, который будет выбран, даже если есть версия для A
.
Специализация разрушит это, потому что кто-то может прийти и специализировать B
для типа U
таким образом, что A<U>
не включает B<U>
.
Итак... что должно произойти тогда? Что происходит, когда кто-то пытается предоставить U
вышеуказанному шаблону с конкурирующими ограничениями? Первичные ограничения говорят о наличии отношения подчинения, а специализированные - нет.
Что еще более важно, могу ли я даже написать две концепции с отношением подчинения и гарантировать, что это будет поддерживаться? То есть, в мире со специализацией, могу ли я полагаться на подчинение в своих интерфейсах шаблонов?
Нет, единственный способ сделать возможным подчинение — это запретить специализацию. Но шаблоны переменных могут быть специализированными. Итак, теперь вам нужна новая конструкция, которая говорит: «Я похож на эту штуку, но вы не можете специализировать меня». Мы могли бы заставить всех печатать template<typename T> [[nonspecialized]] inline constexpr bool concept_name = X
, чтобы получить подчинение (и другие вещи, предусмотренные концепциями).
Или мы могли бы просто сказать template<typename T> concept concept_name = x
и убрать кучу синтаксического шума.
Кроме того, concept
s не могут быть членами классов. Это тоже важно, так как это означает, что вы не можете иметь де-факто специализацию концепции, специализируя класс вокруг концепции.
Кроме того, делая concept
специальной синтаксической конструкцией, представленной собственным грамматическим токеном, это позволяет языку легче использовать concept
в новых местах. Например, std::integral auto var_name = func();
. Компилятор может видеть, что std::integral
— это идентификатор, представляющий понятие. Если он увидит переменную constexpr bool
, возможно, вы захотите использовать ее как концепцию. Или вы, возможно, намеревались использовать его как-то иначе. Делая концепции отдельными вещами, мы устраняем любую двусмысленность.
Это то, что позволяет нам по-разному использовать концепции типов в грамматике, что было бы... сложно без специализированного синтаксиса. Может быть, вы могли бы применить атрибут или что-то еще к constexpr inline bool
, но опять же... зачем все ключевые слова, когда вы просто имеете в виду concept
?