'auto' как заполнитель аргумента шаблона для параметра функции

22

C ++ 20 позволяет использовать autoдля параметра типа функции.

Позволяет ли он также использовать autoв качестве заполнителя аргумента шаблона (не похоже, но в духе C ++ 17 template <auto> в некотором смысле) для типа параметра функции?

Итак, следующий код, предварительно C ++ 20:

template<typename First, typename Second>
void printPair(const std::pair<First, Second>& p) {
    std::cout << p.first << ", " << p.second;
}

Может быть написано как:

void printPair(const std::pair<auto, auto>& p) {
    std::cout << p.first << ", " << p.second;
}

Он компилируется и прекрасно работает с экспериментальной реализацией GCC для концепций.

Это законный синтаксис с C ++ 20?

Амир Кирш
источник
Из того, что я слышал, неограниченное auto напрямую переводится в шаблонизированный typename XYZ, что сильно подразумевает, что это законный синтаксис. Ухоженная .
Fureeish
2
Обратите внимание, что Clang не согласен и что Clang и GCC имеют одинаковые разногласия относительно того auto, разрешено [](const std::pair<auto, auto>& p){}ли (с -std=c++2aили с -std=c++17).
грецкий орех
Спасибо @DavisHerring - я исправил формулировку
Амир Кирш

Ответы:

17

Этот синтаксис действителен в Технической спецификации концепций C ++, но не в C ++ 20. В концепциях C ++ 20 autoдопускается только на верхнем уровне в типе параметра функции. Соответствующее правило - [dcl.spec.auto] параграф 2 :

Заполнитель типа Спецификатор вид типа-ограничение [отказ] autoможет быть использован в качестве ДЕЦЛИ-спецификатор в ДЕЦЛЕ-спецификаторе-SEQ о наличии параметра-декларации в объявлении функции или лямбда-выражении , и, если это не auto спецификатор типа, представляющий тип конечного возврата (см. ниже), является родовым заполнителем типа параметра объявления функции или лямбда-выражения, [Примечание: Наличие заполнителя универсального типа параметра означает, что функция является сокращенным шаблоном функции (9.3.3.5 [dcl.fct]) или лямбда является универсальной лямбда (7.5.5 [expr.prim.lambda]). —Конечная записка]

(Если вы проверите формулировку в самом последнем рабочем проекте на момент написания, вы найдете несколько иное правило. Вышеупомянутое правило было изменено основным вопросом 2447 , который был утвержден в окончательном варианте C ++ 20 в Праге. заседание комитета неделю назад.)

Спецификатор decl s в параметре функции является начальной последовательностью ключевых слов и имен типов в начале объявления параметра. Приведенное выше правило позволяет autoна верхнем уровне:

void f(auto x);

... но только как спецификатор decl . autoне допускается, если вложен в спецификатор decl :

void f(std::vector<auto> x);

... и также не разрешено где-либо еще в типе параметра:

void f(void (*p)(auto));
Ричард Смит
источник
Вау, я этого не знал! Ссылка CWG в настоящее время дает 404, так что вы можете кратко объяснить обоснование этого ограничения?
LF
Это крайне разочаровывает.
Fureeish
1
Извините, проблема CWG и изменение ее формулировки еще не опубликованы. Данное правило было введено open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1141r2.html, и намерение / обоснование должно было соответствовать тому, что мы уже допустили для общих лямбд.
Ричард Смит
4
@LF: Проблема CWG на самом деле не актуальна: она исправила ошибку формулировки, которая подразумевала, что определенные виды использования autoдля конечного возвращаемого типа считаются этим видом autoиспользования.
Дэвис Херринг