Pregunta ¿Cuáles son los 6 puntos en los paquetes de parámetros de la plantilla? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Mientras mira esta pregunta me encontré en el sitio de referencia cpp donde noté una sintaxis extraña y nueva para mí:

template<class Ret, class... Args>
struct is_function<Ret(Args......)volatile &&> : std::true_type {};

Sí, 6 puntos! Inicialmente pensé que esto era un error tipográfico, pero después de verificar el libstdc ++ fuente de nuevo ahí estaba, por ejemplo, en la línea 444:

template<typename _Res, typename... _ArgTypes>
struct is_function<_Res(_ArgTypes......) volatile &&> : public true_type { };

¿Es esto una sintaxis válida? Dot dot dot, ¿se usan para empaquetar y desempaquetar paquetes de parámetros? ¿Qué hacen 6 puntos?


13
2017-12-21 23:06


origen


Respuestas:


En este caso, los dos son para diferentes propósitos. El primero es para la expansión del paquete de parámetros y el segundo es para las listas de argumentos variables. Esa declaración particular es para manejar funciones que toman algunos parámetros regulares más una lista de argumentos variables.

La diferencia está entre el tiempo de ejecución y la variabilidad en tiempo de compilación. Una función que toma una cantidad variable de argumentos en tiempo de ejecución es especial. Es una función única que puede manejar una cantidad variable de argumentos de la persona que llama:

void f(int x,...) // equivalent to void f(int x ...)
{
    // Do some run-time logic here to determine what to
    // do with parameters after x.
}

Esto es distinto de la noción de que queremos poder tener una plantilla que utiliza una variedad de funciones con varios parámetros que se conocen en tiempo de compilación. Por ejemplo, podríamos definir una plantilla de función que toma un puntero a una función y permite variar el número y los tipos de los argumentos:

template <typename... Args>
void g(void (*function_ptr)(Args...)) 
{ 
    // We can do logic here to call function_ptr with the proper
    // number of arguments.
}

Dadas estas funciones:

void f1(int);
void f2(int,float);

Puedes llamar a g con cualquiera de ellos:

g(f1); // fine
g(f2); // also fine

sin embargo

g(f); // error

El compilador no sabría qué usar para el Args paquete de parámetros en g.


8
2017-12-21 23:10



Por que libstdc++ utilizar ... ... en su implementación de is_function? Si miramos la sección de cppreference para std :: is_function da una implementación de muestra y dice por primera ... ... caso:

// specialization for variadic functions such as std::printf
template<class Ret, class... Args>
struct is_function<Ret(Args......)> : std::true_type {};

entonces necesitamos el segundo conjunto de ... para que coincida con una función variadic como printf:

           Comma optional as per 8.3.5 [dcl.fct] 
           |
           v
Ret(Args... ...)
        ^   ^
        |   |
        Match a function with a variable number of arguments
            |
            and the function is a variadic function

Tenga en cuenta que tenemos funciones como fprintf esos dos argumentos antes de los términos variadic y necesitamos unirlos también. De hecho, si usamos esa implementación e intentamos hacer coincidir printf sin el ... ... especialización luego falla verlo en vivo.

Este rincón del lenguaje está cubierto en esta publicación Los seis puntos de C ++ 11:

Estuve jugando el otro día y descubrí esta bonita y pequeña rareza:

template <typename... Args>
void foo(Args......);

Como resultado, ...... puede ser totalmente válido C ++ 11. Esto es lo que sucede cuando la compatibilidad con versiones anteriores se mezcla con el nuevo picor.

// Todos son equivalentes.

template <typename... Args> void foo1(Args......);
template <typename... Args> void foo2(Args... ...);
template <typename... Args> void foo3(Args..., ...);

Esperemos que el último muestre lo que está sucediendo aquí. [...]

¿Por qué es este valild? Podemos ver eso , ... es sinónimo de ... del borrador de la sección estándar de C ++ 11 8.3.5  [dcl.fct] que tiene la siguiente gramática:

parameter-declaration-clause:
  parameter-declaration-listopt...opt
  parameter-declaration-list , ...

y dice:

[...] Donde sintácticamente correcto y donde "..." no es parte de   un declarante abstracto, ", ..." es sinónimo de "...". [...]


54
2017-11-03 15:12