Библиотека концептов (начиная с C++20)
Библиотека концептов предоставляет определения фундаментальных концептов библиотеки, которые можно использовать для проверки аргументов шаблонов во время компиляции и выбора функций на основе свойств типов. Эти концепты служат основой для эквациональных рассуждений в программах.
Большинство концептов стандартной библиотеки предъявляют как синтаксические, так и семантические требования. Стандартный концепт считается удовлетворённым, если выполнены его синтаксические требования, и моделируемым, если он удовлетворён и выполнены его семантические требования (если они есть).
Как правило, компилятор может проверять только синтаксические требования. Если корректность или смысл программы зависит от того, моделирует ли последовательность аргументов шаблона концепт, и концепт удовлетворён, но не моделируется, или если семантическое требование не выполнено в точке использования, программа некорректна, диагностика не требуется.
Сохранение равенства
Выражение сохраняет равенство, если при равных входных данных оно даёт равные выходные данные, где
- входные данные состоят из его операндов (при этом выражение не обязательно семантически корректно), и
- выходные данные состоят из его результата и всех изменений операндов, произведённых выражением, если таковые имеются
где для удобства формулировки под его «операндами» понимаются его наибольшие подвыражения, состоящие из идентификаторного выражения или вызовов std::move, std::forward и std::declval.
CV-квалификация и категория значения каждого операнда определяются исходя из предположения, что каждый параметр типа шаблона в его типе обозначает полный не являющийся массивом тип объекта без CV-квалификации.
Каждое выражение, от которого требуется сохранение равенства, также должно быть стабильным, то есть два его вычисления с одними и теми же входными объектами должны давать равные выходные данные, если между ними не было явного изменения этих входных объектов.
Если не указано иное, каждое выражение, используемое в requires-выражении концептов стандартной библиотеки, должно сохранять равенство; при вычислении выражения могут изменяться только его неконстантные операнды. Константные операнды изменять нельзя.
В стандартной библиотеке следующим концептам разрешены requires-выражения, не сохраняющие равенство:
Неявные варианты выражений
requires-выражение, использующее выражение, которое не изменяет некоторый константный lvalue-операнд, также неявно требует дополнительных вариантов этого выражения, принимающих неконстантный lvalue или (возможно, константный) rvalue для данного операнда, если только такой вариант выражения явно не требуется с отличающейся семантикой.
Эти неявные варианты выражений должны удовлетворять тем же семантическим требованиям, что и объявленное выражение. Степень, в которой реализация проверяет синтаксис этих вариантов, не специфицирована.
template<class T>
concept C = requires(T a, T b, const T c, const T d)
{
c == d; // expression #1: does not modify the operands
a = std::move(b); // expression #2: modifies both operands
a = c; // expression #3: modifies the left operand `a`
};
// Expression #1 implicitly requires additional expression variations that
// meet the requirements for c == d (including non-modification),
// as if the following expressions had been declared as well:
// ------ const == const ------- ------ const == non-const ---
// c == b;
// c == std::move(d); c == std::move(b);
// std::move(c) == d; std::move(c) == b;
// std::move(c) == std::move(d); std::move(c) == std::move(b);
// -- non-const == const ------- -- non-const == non-const ---
// a == d; a == b;
// a == std::move(d); a == std::move(b);
// std::move(a) == d; std::move(a) == b;
// std::move(a) == std::move(d); std::move(a) == std::move(b);
// Expression #3 implicitly requires additional expression variations that
// meet the requirements for a = c
// (including non-modification of the second operand),
// as if the expressions a = b (non-constant lvalue variation)
// and a = std::move(c) (const rvalue variation) had been declared.
// Note: Since expression #2 already requires the non-constant rvalue variation
// (a == std::move(b)) explicitly, expression #3 does not implicitly require it anymore.
// The type T meets the explicitly stated syntactic requirements of
// concept C above, but does not meet the additional implicit requirements
// (i.e., T satisfies but does not model C):
// a program requires C<T> is ill-formed (no diagnostic required).
struct T
{
bool operator==(const T&) const { return true; }
bool operator==(T&) = delete;
};
Концепты стандартной библиотеки
Определены в пространстве имён std |
|
|---|---|
Концепты основного языка |
|
Определены в заголовке <concepts> |
|
|
(C++20) | указывает, что один тип совпадает с другим типом (концепт) |
|
(C++20) | указывает, что один тип является производным от другого типа (концепт) |
|
(C++20) | указывает, что тип неявно преобразуется в другой тип (концепт) |
|
(C++20) | указывает, что у двух типов есть общий тип ссылки (концепт) |
|
(C++20) | указывает, что у двух типов есть общий тип (концепт) |
|
(C++20) | указывает, что тип является целочисленным типом (концепт) |
|
(C++20) | указывает, что тип является целочисленным типом со знаком (концепт) |
|
(C++20) | указывает, что тип является целочисленным типом без знака (концепт) |
|
(C++20) | указывает, что тип является типом с плавающей точкой (концепт) |
|
(C++20) | указывает, что типу можно присвоить значение другого типа (концепт) |
|
(C++20)(C++20) | указывает, что значение типа можно обменять или что значения двух типов можно обменять друг с другом (концепт) |
|
(C++20) | указывает, что объект типа можно уничтожить (концепт) |
|
(C++20) | указывает, что переменную типа можно сконструировать из набора типов аргументов или привязать к нему (концепт) |
|
(C++20) | указывает, что объект типа можно сконструировать по умолчанию (концепт) |
|
(C++20) | указывает, что объект типа можно сконструировать перемещением (концепт) |
|
(C++20) | указывает, что объект типа можно сконструировать копированием и перемещением (концепт) |
Концепты сравнения |
|
Определены в заголовке <concepts> |
|
|
(C++20) | указывает, что тип можно использовать в булевых контекстах (концепт, используемый только для иллюстрации*) |
|
(C++20)(C++20) | указывает, что оператор == является отношением эквивалентности (концепт) |
|
(C++20)(C++20) | указывает, что операторы сравнения для типа задают полный порядок (концепт) |
Определены в заголовке <compare> |
|
|
(C++20)(C++20) | указывает, что оператор <=> даёт согласованный результат для заданных типов (концепт) |
Концепты объектов |
|
Определены в заголовке <concepts> |
|
|
(C++20) | указывает, что объект типа можно перемещать и менять местами (концепт) |
|
(C++20) | указывает, что объект типа можно копировать, перемещать и менять местами (концепт) |
|
(C++20) | указывает, что объект типа можно копировать, перемещать, менять местами и конструировать по умолчанию (концепт) |
|
(C++20) | указывает, что тип является регулярным, то есть одновременно удовлетворяет концептам semiregular и equality_comparable (концепт) |
Концепты вызываемых объектов |
|
Определены в заголовке <concepts> |
|
|
(C++20)(C++20) | указывает, что вызываемый тип можно вызвать с заданным набором типов аргументов (концепт) |
|
(C++20) | указывает, что вызываемый тип является булевым предикатом (концепт) |
|
(C++20) | указывает, что вызываемый тип является бинарным отношением (концепт) |
|
(C++20) | указывает, что relation задаёт отношение эквивалентности (концепт) |
|
(C++20) | указывает, что relation задаёт строгое слабое упорядочение (концепт) |
Дополнительные концепты можно найти в библиотеке итераторов, библиотеке алгоритмов и библиотеке диапазонов.
См. также
© cppreference.com
Licensed under the Creative Commons Attribution-ShareAlike Unported License v3.0.
https://en.cppreference.com/cpp/concepts