En C ++ 11 hay plantillas variadas como esta:
template< class T, class... Args >
unique_ptr<T> make_unique( Args&&... args )
{
return unique_ptr<T>(new T(std::forward<Args>(args)...));
}
Hay algunas curiosidades sobre esto: la expresión std::forward<Args>(args)...
usa ambos Args
y, args
pero solo una ...
ficha. Además, std::forward
es una función de plantilla no variada que toma solo un parámetro de plantilla y un argumento. ¿Cuáles son las reglas de sintaxis para eso (aproximadamente)? ¿Cómo se puede generalizar?
Además: en la implementación de la función, la elipsis ( ...
) está al final de la expresión de interés. ¿Hay alguna razón por la que en la lista de argumentos de la plantilla y en la lista de parámetros la elipsis está en el medio?
c++
c++11
variadic-templates
Ralph Tandetzky
fuente
fuente
...
viene antes del identificador que se introduce. Al usar uno o ambos tipos de paquetes, el...
viene después del patrón de expresión para expandirse.Respuestas:
En el contexto de la plantilla variadica, la elipsis
...
se usa para descomprimir el paquete de parámetros de la plantilla si aparece en el lado derecho de una expresión (llame a esta expresión patrón por un momento). La regla es que cualquier patrón que esté en el lado izquierdo de...
se repite; los patrones desempaquetados (llámelos expresiones ahora) están separados por comas,
.Puede entenderse mejor con algunos ejemplos. Suponga que tiene esta plantilla de función:
Ahora, si llamo a esta función pasando
T
como{int, char, short}
, entonces cada llamada de función se expande como:En el código que publicó,
std::forward
sigue el cuarto patrón ilustrado por lan()
llamada a la función.¡Note la diferencia entre
x(args)...
yy(args...)
arriba!Puede usar
...
para inicializar una matriz también como:que se expande a esto:
Me acabo de dar cuenta de que un patrón podría incluso incluir un especificador de acceso como
public
, como se muestra en el siguiente ejemplo:En este ejemplo, el patrón se expande como:
Es decir,
mixture
deriva públicamente de todas las clases base.Espero que ayude.
fuente
x+args...
debería ampliarse ax+arg0,x+arg1,x+arg2
, nox+arg0,arg1,arg2
....
aplica a todas las entidades expandibles del patrón.x+args...
debería expandirse ax+arg0,x+arg1,x+arg2
, nox+arg0,arg1,arg2
.sizeof...(T)
no se necesita allí. Simplemente puede escribir:int a[] = { ___ };
Lo siguiente fue tomado de la charla "Las plantillas variadas son Funadic" por Andrei Alexandrescu en GoingNative 2012. Puedo recomendarlo para una buena introducción a las plantillas variadas.
Hay dos cosas que se pueden hacer con un paquete variadic. Es posible aplicar
sizeof...(vs)
para obtener el número de elementos y expandirlo.Reglas de expansión
La expansión procede hacia adentro hacia afuera. Al expandir dos listas en el paso de bloqueo, deben tener el mismo tamaño.
Más ejemplos:
Expande todo
Ts
en la lista de argumentos de la plantilla deA
y luego la funciónhun
se expande con todovs
.Expande todo
Ts
en la lista de argumentos de plantilla deA
y todosvs
como argumentos de función parahun
.Expande la función
hun
conTs
yvs
en paso de bloqueo.Nota:
Ts
no es un tipo yvs
no es un valor. Son alias para una lista de tipos / valores. Cualquiera de las dos listas puede estar potencialmente vacía. Ambos obedecen solo a acciones específicas. Entonces lo siguiente no es posible:Loci de expansión
Argumentos de función
Listas de inicializadores
Especificadores de base
Listas de inicializadores de miembros
Listas de argumentos temáticos
Solo se compilará si hay una posible coincidencia para los argumentos.
Capturar listas
Listas de atributos
Está en la especificación, pero todavía no hay ningún atributo que pueda expresarse como un tipo.
fuente