Зачем нам нужно ключевое слово concept в C++20?

Концепции великолепны, не поймите меня неправильно, но зачем нам для этого еще одно ключевое слово?

Рассмотрим следующий пример:

#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-предложения можно использовать с шаблонами переменных, поскольку они представляют собой просто выражения, которые оцениваются как логические значения во время компиляции.

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

463035818_is_not_a_number 20.02.2023 18:36

«концепции - это не что иное, как логические константы времени компиляции». Существуют правила включения, которые работают с понятиями (а не с базовыми условиями).

Jarod42 20.02.2023 18:38

Еще не читал его, но я ожидаю, что здесь можно найти хорошую мотивацию: open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1886.pdf

463035818_is_not_a_number 20.02.2023 18:42

Помимо правил включения, которые обеспечивают некоторую ценную ясность кода, ваш пример не демонстрирует, как UnsignedConst auto будет работать как тип. В основном его можно синтезировать на C++17, но он довольно уродлив и многословен, и людям трудно его читать.

Drew Dormann 20.02.2023 19:20

Я знаю о шаблонах переменных, я просто думал, что концепции не нужны из-за их существования.

M Qwadezo 20.02.2023 19:21

Тогда ваш вопрос не очень хорошо сформулирован, он говорит только о синтаксисе и о введении ключевого слова. С другой стороны, шаблоны переменных против концепций - это около 2 языковых функций.

463035818_is_not_a_number 20.02.2023 19:46
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Инструменты для веб-скрапинга с открытым исходным кодом: Python Developer Toolkit
Веб-скрейпинг, как мы все знаем, это дисциплина, которая развивается с течением времени. Появляются все более сложные средства борьбы с ботами, а...
Калькулятор CGPA 12 для семестра
Калькулятор CGPA 12 для семестра
Чтобы запустить этот код и рассчитать CGPA, необходимо сохранить код как HTML-файл, а затем открыть его в веб-браузере. Для этого выполните следующие...
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
ONLBest Online HTML CSS JAVASCRIPT Training In INDIA 2023
О тренинге HTML JavaScript :HTML (язык гипертекстовой разметки) и CSS (каскадные таблицы стилей) - две основные технологии для создания веб-страниц....
Как собрать/развернуть часть вашего приложения Angular
Как собрать/развернуть часть вашего приложения Angular
Вам когда-нибудь требовалось собрать/развернуть только часть вашего приложения Angular или, возможно, скрыть некоторые маршруты в определенных средах?
Запуск PHP на IIS без использования программы установки веб-платформы
Запуск PHP на IIS без использования программы установки веб-платформы
Установщик веб-платформы, предлагаемый компанией Microsoft, перестанет работать 31 декабря 2022 года. Его закрытие привело к тому, что мы не можем...
Оптимизация React Context шаг за шагом в 4 примерах
Оптимизация React Context шаг за шагом в 4 примерах
При использовании компонентов React в сочетании с Context вы можете оптимизировать рендеринг, обернув ваш компонент React в React.memo сразу после...
1
6
115
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
Под капотом концепции — это не что иное, как логические константы времени компиляции, зависящие от параметров шаблона.

Это неправда.

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 и убрать кучу синтаксического шума.

Кроме того, concepts не могут быть членами классов. Это тоже важно, так как это означает, что вы не можете иметь де-факто специализацию концепции, специализируя класс вокруг концепции.

Кроме того, делая concept специальной синтаксической конструкцией, представленной собственным грамматическим токеном, это позволяет языку легче использовать concept в новых местах. Например, std::integral auto var_name = func();. Компилятор может видеть, что std::integral — это идентификатор, представляющий понятие. Если он увидит переменную constexpr bool, возможно, вы захотите использовать ее как концепцию. Или вы, возможно, намеревались использовать его как-то иначе. Делая концепции отдельными вещами, мы устраняем любую двусмысленность.

Это то, что позволяет нам по-разному использовать концепции типов в грамматике, что было бы... сложно без специализированного синтаксиса. Может быть, вы могли бы применить атрибут или что-то еще к constexpr inline bool, но опять же... зачем все ключевые слова, когда вы просто имеете в виду concept?

Другие вопросы по теме