Избегайте «концептов» без содержательной семантики
Причина
Концепты призваны выражать семантические понятия, такие как «число», «диапазон» элементов и «полный порядок». Простые ограничения, такие как «имеет оператор +» и «имеет оператор >», не могут быть содержательно заданы в изоляции и должны использоваться только как строительные блоки для содержательных концептов, а не напрямую в пользовательском коде.
Пример (плохой)
template<typename T>
// плохо; недостаточно
concept Addable = requires(T a, T b) { a + b; };
template<Addable N>
auto algo(const N& a, const N& b) // используем два числа
{
// ...
return a + b;
}
int x = 7;
int y = 9;
auto z = algo(x, y); // z = 16
string xx = "7";
string yy = "9";
auto zz = algo(xx, yy); // zz = "79"
Возможно, ожидалась конкатенация. Скорее всего, это было случайностью. Аналогичное определение через вычитание дало бы кардинально разные множества принимаемых типов. Данный Addable нарушает математическое правило о том, что сложение должно быть коммутативным: a+b == b+a.
Примечание
Способность задавать содержательную семантику — определяющая характеристика настоящего концепта, в отличие от синтаксического ограничения.
Пример
template<typename T>
// Предполагается, что операторы +, -, * и / для числа следуют обычным математическим правилам
concept Number = requires(T a, T b) { a + b; a - b; a * b; a / b; };
template<Number N>
auto algo(const N& a, const N& b)
{
// ...
return a + b;
}
int x = 7;
int y = 9;
auto z = algo(x, y); // z = 16
string xx = "7";
string yy = "9";
auto zz = algo(xx, yy); // ошибка: string не является Number
Примечание
Концепты с несколькими операциями значительно реже случайно совпадают с каким-либо типом, чем концепты с одной операцией.
Контроль
- Помечать одноопе рационные
concepts, используемые за пределами определения другихconcepts. - Помечать использование
enable_if, которое имитирует одноопе рационныеconcepts.