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 вводит пары (итератор, дозорный), что заставляет общий код использовать два разных типа в любом случае.