С++ 20: концепции нескольких типов и их ограничения, правильный синтаксис? - программирование
Подтвердить что ты не робот

С++ 20: концепции нескольких типов и их ограничения, правильный синтаксис?

Подтверждено, что в следующем стандарте 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 Бьярно Страуструпа, но я не смог найти его после быстрого взгляда.

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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);

Ответ 3

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

bool are_equal(auto x,auto y)
  requires AreEqComparable<decltype(x),decltype(y)>
  {return x==y;}

Ответ 4

В 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 для включения концепций.