'auto' como um espaço reservado para argumento de modelo para um parâmetro de função

22

C ++ 20 permite usar o autotipo de parâmetro de função.

Também permite usar autocomo um espaço reservado para argumento de modelo (não semelhante, mas no espírito do modelo C ++ 17 <auto> de certa forma) para o tipo de parâmetro de função?

Portanto, o código a seguir, antes do C ++ 20:

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

Pode ser escrito como:

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

Ele compila e funciona bem com a implementação experimental do GCC para conceitos.

É uma sintaxe legítima com C ++ 20?

Amir Kirsh
fonte
Pelo que ouvi, irrestrito auto se traduz diretamente em templatizado typename XYZ, o que implicaria fortemente que é a sintaxe legítima. Limpo .
Fureeish
2
Observe que Clang discorda e que Clang e GCC têm o mesmo desacordo sobre se autoé permitido entrar [](const std::pair<auto, auto>& p){}(seja com -std=c++2aou -std=c++17).
noz
Obrigado @DavisHerring - Corrigi a redação
Amir Kirsh

Respostas:

17

Essa sintaxe é válida na Especificação técnica dos conceitos do C ++, mas não no C ++ 20. Nos conceitos do C ++ 20, autoé permitido apenas no nível superior em um tipo de parâmetro de função. A regra relevante é o [dcl.spec.auto] parágrafo 2 :

Um especificador de tipo de espaço reservado da restrição de tipo de formulário [opt] autopode ser usado como um especificador de declínio do decl-specifier-seq de uma declaração de parâmetro de uma declaração de função ou expressão lambda e, se não for o auto O especificador de tipo que introduz um tipo de retorno à direita (veja abaixo) é um espaço reservado de tipo de parâmetro genérico da declaração da função ou expressão lambda. [Nota: Ter um espaço reservado genérico para o tipo de parâmetro significa que a função é um modelo de função abreviado (9.3.3.5 [dcl.fct]) ou o lambda é um lambda genérico (7.5.5 [expr.prim.lambda]). - end note]

(Se você verificar a redação do rascunho de trabalho mais recente no momento da redação deste documento, encontrará uma regra um pouco diferente. A regra acima foi modificada pela edição principal 2447 , que foi votada na minuta final do C ++ 20 em Praga. reunião do comitê há uma semana.)

O especificador de declínio s em um parâmetro de função é a sequência inicial de palavras-chave e nomes de tipos no início da declaração do parâmetro. A regra acima permite autoque no nível superior:

void f(auto x);

... mas apenas como um especificador de declínio . autonão é permitido quando aninhado dentro de um especificador de declínio :

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

... e também não é permitido em outro lugar no tipo de parâmetro:

void f(void (*p)(auto));
Richard Smith
fonte
Uau, eu não sabia disso! Atualmente, o link do CWG fornece 404, então você pode explicar brevemente a justificativa para essa restrição?
LF
Isso é totalmente decepcionante.
Fureeish 23/02
11
Desculpe, o problema do CWG e sua alteração de texto ainda não estão visíveis publicamente. A regra em questão foi introduzida por open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1141r2.html e a intenção / racionalidade deve ser consistente com o que já permitimos para lambdas genéricas.
Richard Smith
4
@LF: o problema do CWG não é realmente relevante de qualquer maneira: ele corrigiu um erro de formulação que implicava que certos usos de autoum tipo de retorno à direita contados como esse tipo de autouso.
Davis Herring