C ++ 20: концепции нескольких типов и их ограничения, правильный синтаксис? - PullRequest
18 голосов
/ 11 июля 2019

Похоже, что в следующем стандарте c++20, согласно в этом отчете Reddit , мы сможем определить концепцию шаблона и для каждогоШаблон класса / функции, мы сможем установить ограничения для его типов.Однако в документациях и учебных пособиях (например, здесь ) я не смог найти правильный синтаксис для варианта использования нескольких типов.


Предположим, у нас есть концепция нескольких типов:

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 от Bjarne Stroustrup , но я слишком долго читаю.

Ответы [ 4 ]

12 голосов
/ 11 июля 2019

Вы можете написать это так:

template <typename T1, typename T2>
    requires AreEqComparable<T1, T2>
bool are_equal(T1 a, T2 b)
{
    // ...
}

Здесь мы используем require-clause , чтобы наложить требование на параметры шаблона типа.

8 голосов
/ 11 июля 2019

Вы можете написать:

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>. Это, безусловно, будет иметь значение для многих концепций, но, вероятно, не для этого, в частности, поскольку == само становится симметричным в C ++ 20 (если не считать патологических случаев, которых не должно быть в реальном коде). И если вы хотите на действительно быть уверенным, что эта симметрия действительна, вы всегда можете сделать ее явной в концепции (так как EqualityComparableWith в рабочем проекте):

template<typename T1, typename T2>
concept AreEqComparable = requires(T1 a, T2 b) {
    { a == b } -> bool;
    { b == a } -> bool;
};
<ч />

На самом деле вы можете получить желаемое ограничение в правильном порядке, переключив порядок параметров шаблона (ч / т Матье. M):

template <typename T2, AreEqComparable<T2> T1>
bool are_equal(T1, T2);
3 голосов
/ 11 июля 2019

Еще один синтаксис, который вообще не позволяет вводить параметры шаблона (за счет добавления другой избыточности):

bool are_equal(auto x,auto y)
  requires AreEqComparable<decltype(x),decltype(y)>
  {return x==y;}
2 голосов
/ 12 июля 2019

В GCC 8.2.0 концепции должны быть записаны так:

concept bool ConceptName = /* ... */

Но Шаблоны C ++: Полное руководство не упоминает bool. Поскольку стандарт C ++ 20 не выпущен, трудно сказать, что правильно.

Для понятий, которым нужен один параметр (необязательно тип), есть сокращение:

template <UnaryConceptName T>

Для тех, кому нужны два или более параметров, сокращений нет:

template <typename T1, typename T2> requires BinaryConceptName<T1, T2>

typename можно заменить конкретным именем типа.

Кстати:

  1. Книга, о которой я упоминал выше, дает краткое введение в понятия.

  2. используйте -fconcepts в GCC для включения концепций.

...