'auto' como marcador de posición de argumento de plantilla para un parámetro de función

22

C ++ 20 permite usar el autotipo de parámetro de función.

¿También permite usar autocomo un marcador de posición de argumento de plantilla (no similar, pero en el espíritu de la plantilla C ++ 17 <auto> de alguna manera) para el tipo de parámetro de función?

Entonces, el siguiente código, pre C ++ 20:

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

Podría escribirse como:

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

Se hace de compilación y funciona muy bien con la implementación experimental para GCC conceptos.

¿Es una sintaxis legítima con C ++ 20?

Amir Kirsh
fuente
Por lo que he escuchado, sin restricciones auto se traduce directamente en plantilla typename XYZ, lo que implicaría que es la sintaxis legítima. Aseado .
Fureeish
2
Tenga en cuenta que Clang no está de acuerdo y que Clang y GCC tienen el mismo desacuerdo sobre si autoestá permitido [](const std::pair<auto, auto>& p){}(ya sea con -std=c++2ao -std=c++17).
nogal
Gracias @DavisHerring - He arreglado la redacción
Amir Kirsh

Respuestas:

17

Esta sintaxis es válida en la Especificación técnica de conceptos de C ++, pero no en C ++ 20. En los conceptos de C ++ 20, autosolo se permite en el nivel superior en un tipo de parámetro de función. La regla relevante es [dcl.spec.auto] párrafo 2 :

Un especificador de tipo de marcador de posición de la restricción de tipo de formulario [opt] autopuede usarse como un especificador de declinación de la seq-especificador de declinación de una declaración de parámetro de una declaración de función o expresión lambda y, si no es el auto El especificador de tipo que introduce un tipo de retorno final (ver más abajo) es un marcador de posición de tipo de parámetro genérico de la declaración de función o expresión lambda. [Nota: Tener un marcador de posición de tipo de parámetro genérico significa que la función es una plantilla de función abreviada (9.3.3.5 [dcl.fct]) o que la lambda es una lambda genérica (7.5.5 [expr.prim.lambda]). —Nota final]

(Si marca la redacción en el borrador de trabajo más reciente al momento de escribir, encontrará una regla algo diferente. La regla anterior fue modificada por el tema central 2447 , que fue votado en el borrador final de C ++ 20 en Praga reunión del comité hace una semana.)

Los especificadores de declinación en un parámetro de función son la secuencia inicial de palabras clave y nombres de tipo al comienzo de la declaración del parámetro. La regla anterior permite autoallí en el nivel superior:

void f(auto x);

... pero solo como un especificador de declinación . autono está permitido cuando está anidado dentro de un especificador de declinación :

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

... y tampoco está permitido en otra parte del tipo de parámetro:

void f(void (*p)(auto));
Richard Smith
fuente
¡Wow, no lo sabía! El enlace CWG actualmente da 404, entonces, ¿puede explicar brevemente la justificación de esta restricción?
LF
Esto es completamente decepcionante.
Fureeish
1
Lo sentimos, el problema de CWG y su cambio de redacción aún no son visibles públicamente. La regla en cuestión fue introducida por open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1141r2.html y la intención / razón era ser coherente con lo que ya permitimos para lambdas genéricos.
Richard Smith
44
@LF: El problema de CWG no es realmente relevante de todos modos: corrigió un error de redacción que implicaba que ciertos usos de autoun tipo de retorno final contaban como este tipo de autouso.
Davis Herring