No C ++ 11, existem modelos variados como este:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Existem algumas curiosidades sobre isso: A expressão std::forward<Args>(args)...
usa ambos Args
e, args
mas apenas um ...
token. Além disso, std::forward
é uma função de modelo não variável que usa apenas um parâmetro de modelo e um argumento. Quais são as regras de sintaxe para isso (aproximadamente)? Como pode ser generalizado?
Além disso: Na implementação da função, as reticências ( ...
) estão no final da expressão de interesse. Existe uma razão para que na lista de argumentos do modelo e na lista de parâmetros as reticências estejam no meio?
c++
c++11
variadic-templates
Ralph Tandetzky
fonte
fonte
...
vem antes do identificador ser introduzido. Ao usar um ou ambos os tipos de pacotes, o...
vem após o padrão de expressão para expandir.Respostas:
No contexto do modelo variadic, as reticências
...
são usadas para descompactar o pacote de parâmetros do modelo se ele aparecer no lado direito de uma expressão (chame este padrão de expressão por um momento). A regra é que qualquer padrão que esteja no lado esquerdo de...
é repetido - os padrões descompactados ( agora chame-os de expressões ) são separados por vírgula,
.Pode ser melhor compreendido por alguns exemplos. Suponha que você tenha este modelo de função:
Agora, se eu chamar essa função passando
T
como{int, char, short}
, cada uma das chamadas de função será expandida como:No código que você postou,
std::forward
segue o quarto padrão ilustrado pelan()
chamada de função.Observe a diferença entre
x(args)...
ey(args...)
acima!Você também pode usar
...
para inicializar uma matriz como:que é expandido para este:
Acabei de perceber que um padrão pode até incluir especificador de acesso
public
, como mostrado no exemplo a seguir:Neste exemplo, o padrão é expandido como:
Ou seja,
mixture
deriva publicamente de todas as classes base.Espero que ajude.
fonte
x+args...
deve ser expandido parax+arg0,x+arg1,x+arg2
, nãox+arg0,arg1,arg2
....
aplica-se a todas as entidades expansíveis no padrão.x+args...
deve expandir parax+arg0,x+arg1,x+arg2
, nãox+arg0,arg1,arg2
.sizeof...(T)
não é necessário lá. Você pode simplesmente escrever:int a[] = { ___ };
O que se segue foi retirado da palestra "Variadic Templates are Funadic" por Andrei Alexandrescu em GoingNative 2012. Posso recomendá-lo para uma boa introdução sobre modelos variadic.
Existem duas coisas que podem ser feitas com um pacote variadic. É possível aplicar
sizeof...(vs)
para obter o número de elementos e expandi-lo.Regras de expansão
A expansão prossegue de dentro para fora. Ao expandir duas listas em etapa de bloqueio, elas devem ter o mesmo tamanho.
Mais exemplos:
Expande tudo
Ts
na lista de argumentos do modelo deA
e, em seguida, a funçãohun
é expandida com todosvs
.Expande tudo
Ts
na lista de argumentos do modelo deA
e todosvs
como os argumentos da função parahun
.Expande a função
hun
comTs
evs
em etapas.Nota:
Ts
não é um tipo evs
não é um valor! Eles são apelidos para uma lista de tipos / valores. Qualquer uma das listas pode estar potencialmente vazia. Ambos obedecem apenas a ações específicas. Portanto, o seguinte não é possível:Loci de expansão
Argumentos de função
Listas de inicializadores
Especificadores de base
Listas de inicializadores de membros
Listas de argumentos temporárias
Só será compilado se houver uma correspondência possível para os argumentos.
Listas de captura
Listas de atributos
Está na especificação, mas ainda não há nenhum atributo que possa ser expresso como um tipo.
fonte