Mientras navegaba por la implementación actual de gcc de los nuevos encabezados de C ++ 11, me topé con el token "......". Puede comprobar que el siguiente código se compila bien [a través de ideone.com].
template <typename T>
struct X
{ /* ... */ };
template <typename T, typename ... U>
struct X<T(U......)> // this line is the important one
{ /* ... */ };
Entonces, ¿cuál es el significado de esta ficha?
editar: Parece TAN recortado "......" en el título de la pregunta a "...", realmente quise decir "......". :)
c++
c++11
variadic-templates
Vitus
fuente
fuente
...
sigue...
.U...
seguido de...
. No obstante, muy extraño.<functional>
y<type_traits>
, siempre en el contexto de una lista de argumentos de función dentro de un parámetro de plantilla.Respuestas:
Cada instancia de esa rareza se empareja con un caso de una sola elipsis regular.
Supongo que la elipsis doble tiene un significado similar a
_ArgTypes..., ...
, es decir, una expansión de plantilla variada seguida de una lista de varargs de estilo C.Aquí hay una prueba que respalda esa teoría ... Creo que tenemos un nuevo ganador para el peor pseudo operador de la historia.
Editar: Esto parece ser conforme. §8.3.5 / 3 describe una forma de formar la lista de parámetros como
Entonces, la elipsis doble está formada por una lista de declaración de parámetros que termina con un paquete de parámetros, seguida de otra elipsis.
La coma es puramente opcional; §8.3.5 / 4 dice
Esto está dentro de un declarador abstracto, [editar] pero Johannes hace un buen punto de que se refieren a un declarador abstracto dentro de una declaración de parámetro. Me pregunto por qué no dijeron "parte de una declaración de parámetro" y por qué esa oración no es solo una nota informativa ...
Además,
va_begin()
in<cstdarg>
requiere un parámetro antes de la lista de varargs, por lo que el prototipof(...)
específicamente permitido por C ++ es inútil. Hacer referencias cruzadas con C99, es ilegal en simple C. Entonces, esto es de lo más extraño.Nota de uso
A pedido, aquí hay una demostración de la doble elipsis:
fuente
std::is_function
'svalue
debe ser verdadero incluso si la función es C varargs one y porque T (U ...) no coincide con dicha función, necesitas esta locura. Por ejemplo, int f (int, char, ...) coincide con T (U ......) exactamente con T = int, U = {int, char} y el token varargs "...".void (int...)
, aquí...
no es parte del declarador abstractoint
, por lo que es sinónimo devoid(int, ...)
. Si escribieravoid(T...)
yT
es un paquete de parámetros de plantilla,...
sería parte del declarador abstracto y, por lo tanto, no sería equivalente avoid(T, ...)
.f(...)
se usa mucho como una sobrecarga de funciones de respaldo en la metaprogramación de plantillas, donde esta información no es necesaria (y donde la función ni siquiera se llama).en vs2015 separar la coma es esencial en la versión de plantilla:
una instanciación de ejemplo es:
saludos, FM.
fuente