Подтвердить что ты не робот

Концепции С++ с несколькими аргументами шаблона

Bjarne Stroustrup недавно опубликовал отчет в концепциях С++, где он упоминает то, что казалось мне удивительным. В примере (в разделе 7.1) используется "сокращенное обозначение шаблона" и, по сути, выглядит следующим образом:

void foo1(auto x,auto y);                // x and y may have different types  (1)
void foo2(SomeConcept x,SomeConcept y);  // x and y must have the same type   (2)

Для меня лично это кажется очень противоречивым; на самом деле, я ожидал бы, что foo2 примет значения x, y разных типов, если соответствующие типы удовлетворяют SomeConcept. Обратите внимание, что программист всегда может явно указать свое намерение, написав одно из следующего:

template <SomeConcept T> void foo2(T x, T y);                   // (3)
template <SomeConcept T1,SomeConcept T2> void foo2(T1 x,T2 y);  // (4)

Интуитивно я ожидал бы, что сокращенная запись из (2) будет эквивалентна (4) и, следовательно, будет более соответствовать смыслу неограниченного шаблона (1). Может ли кто-нибудь пролить свет на это дело и объяснить обоснование этого решения?

Некоторые замечания:

  • afaik, generic lambdas (в С++ 14) уже позволяют использовать синтаксис, аналогичный (1). Следовательно, согласованность диктует, что (1) должен принимать входные переменные с разными типами, поскольку общие лямбды делают это.
  • Строуступ упоминает классическую "пару итераторов" в контексте таких шаблонов. Тем не менее, я считаю, что это довольно слабый аргумент, поскольку (i) это всего лишь один случай использования и (ii) afaik, С++ 17 вводит пары (итератор, дозорный), что заставляет общий код использовать два разных типа в любом случае.
4b9b3361

Ответ 1

Самый ранний документ, который я мог бы найти, упоминает краткий синтаксис в контексте настоящего предложения концепций N3580, который в § 6.2.2 дает такое обоснование:

Что делать, если нам нужны два типа аргументов одного и того же понятия? Рассмотрим

void sort(Ran p, Ran q);

Чтобы это имело смысл, p и q должны быть одного типа, и это правило. По умолчанию, если вы используете одно и то же имя ограниченных параметров для двух аргументов, типы этих аргументов должны быть одинаковыми. Мы решили сделать повторное использование ограниченного имени параметра подразумевающим "тот же тип", потому что это (в большинстве сред) является наиболее распространенным случаем, и целью здесь является оптимизация для краткое обозначение простейшего случая. Кроме того, ограниченным параметром является имя типа и имеющие два типа имен относятся к разным типам в одной области приведет к хаосу.

У Тони ван Эйрда и Ботона Балло есть предложение изменить это значение: P0464. В документе представлены два аргумента в поддержку текущих значений, аналогичных одному из Sutton et al., И одного ортогонального:

Частота использования
Можно утверждать, что вам часто не нужна функция, которая принимает два аргумента потенциально разных типов, удовлетворяющих одному и тому же понятию, без дополнительной взаимосвязи между этими двумя типами.

Взаимодействие с проверкой определения
Можно также утверждать, что это изменение побудит авторов шаблонов писать шаблоны с ограниченным ограничением, потому что они предпочтут использовать краткую форму R foo(ConceptName, ConceptName); даже в тех случаях, когда должно быть дополнительное ограничение на типы параметров. Распространение шаблонов с ограниченным ограничением упростит введение проверки определений, поскольку шаблон с ограниченным ограничением не пройдет проверку определений.


Я не знаком с каким-либо другим аргументом в пользу текущего синтаксиса, но если да, не стесняйтесь направить Тони и Ботонда для включения в их статью.

Ответ 2

Просто быстрое обновление для тех, кто отметил этот вопрос или нашел его в Google.

Обсуждаемый здесь вопрос был решен - по-видимому, молча - до совещания по стандартам C++ в Джексонвилле, март 2018 года. Цитата из отчета о поездке Botond:

Кроме того, одной темой, которая, кажется, была решена без особого обсуждения, был вопрос о независимом разрешении или последовательном разрешении; то есть, если у вас есть два использования одного и того же понятия в AFT (как в void foo(Number, Number);), требуется ли, чтобы они были одного и того же конкретного типа ("непротиворечивый") или двух потенциально разных типов, которые оба смоделировать концепцию ("независимая"). Концепции TS имеет последовательное разрешение, но многие люди предпочитают независимое разрешение. Некоторое время назад я стал соавтором статьи, выступающей за независимое разрешение; это мнение впоследствии было подкреплено другим документом, а также в разделе предложения Sortable{S}. В некотором смысле, к моему удивлению, эта тема никогда не обсуждалась и формально не обсуждалась; Идея независимого урегулирования, казалось, медленно, со временем завоевывала людей, так что к этой встрече это было отчасти расценено как сделка, что любое предложение AFT, входящее в C++ 20, фактически будет иметь независимое разрешающая способность.