Ответ 1
Вы можете написать это так:
template <typename T1, typename T2>
requires AreEqComparable<T1, T2>
bool are_equal(T1 a, T2 b)
{
// ...
}
Здесь мы используем условие require для наложения требования на параметры шаблона типа.
Подтверждено, что в следующем стандарте c++20
, в соответствии с , в этом отчете Reddit из недавнего Кельнского совещания ISO C++, мы сможем указать шаблон Концепция и для каждого шаблона класса/функции мы сможем установить ограничения constraints для его типов. Однако в документациях и учебных руководствах (например, здесь) я не смог найти правильный синтаксис для варианта использования нескольких типов.
Предположим, у нас есть концепция нескольких типов:
template<typename T1, typename T2>
concept AreEqComparable = requires(T1 a, T2 b) {
{ a == b } -> bool;
};
Допустим, я хочу определить простую функцию сравнения между двумя разными типами. Как я могу это сделать? Более конкретно, что я должен написать в ???
части кода ниже:
???
bool are_equal(T1 a, T2 b) { return a == b; }
Я не смог найти никакой ссылки на этот случай в здесь, здесь и даже здесь. Я случайно попробовал что-то вроде:
/* 1 */ template<AreEqComparable T1, T2>
/* 2 */ AreEqComparable<T1, T2>
/* 3 */ template<AreEqComparable<T1, T2>>
Но все они выдают синтаксические ошибки. Я думаю, что ответ должен лежать где-то в спецификации P0557 Бьярно Страуструпа, но я не смог найти его после быстрого взгляда.
Вы можете написать это так:
template <typename T1, typename T2>
requires AreEqComparable<T1, T2>
bool are_equal(T1 a, T2 b)
{
// ...
}
Здесь мы используем условие require для наложения требования на параметры шаблона типа.
Вы можете написать:
template <typename T1, AreEqComparable<T1> T2>
bool are_equal(T1, T2);
Это эквивалентно:
template <typename T1, typename T2>
requires AreEqComparable<T2, T1>
bool are_equal(T1, T2);
Типы здесь отображаются в ограничении, AreEqComparable<T2, T1>
вместо AreEqComparable<T1, T2>
. Это, безусловно, будет иметь значение для многих концепций, но, вероятно, не для этого, в частности, поскольку сам TG44 становится симметричным в С++ 20 (если не считать патологических случаев, которых не должно быть в реальном коде). И если вы хотите быть действительно уверенными в том, что эта симметрия действительна, вы всегда можете сделать ее явной в концепции (как EqualityComparableWith
в рабочем проекте):
template<typename T1, typename T2>
concept AreEqComparable = requires(T1 a, T2 b) {
{ a == b } -> bool;
{ b == a } -> bool;
};
На самом деле вы можете получить нужное ограничение в правильном порядке, щелкнув порядок параметров шаблона (ч/т Мэтью М.):
template <typename T2, AreEqComparable<T2> T1>
bool are_equal(T1, T2);
Еще один синтаксис, который вообще избегает введения параметров шаблона (за счет добавления другой избыточности):
bool are_equal(auto x,auto y)
requires AreEqComparable<decltype(x),decltype(y)>
{return x==y;}
В GCC 8.2.0 концепции должны быть написаны так:
concept bool ConceptName = /* ... */
Но шаблоны C++: Полное руководство не упоминает bool
. Поскольку стандарт C++ 20 не выпущен, трудно сказать, что правильно.
Для понятий, которым нужен один параметр (необязательно тип), есть сокращение:
template <UnaryConceptName T>
Для тех, которые нуждаются в двух или более параметрах, сокращений нет:
template <typename T1, typename T2> requires BinaryConceptName<T1, T2>
typename
может быть заменено определенным именем типа.
Кстати:
Книга, которую я упоминал выше, дает краткое введение в понятия.
используйте -fconcepts
в GCC для включения концепций.