Pregunta

he visto una gran cantidad de enlaces que introducen las plantillas variadic. Pero nunca he visto ningún ejemplo compilables que muestra este método.

Podría alguien proporcionarme algunos enlaces en los que estos ejemplos se pueden encontrar compilables?

¿Fue útil?

Solución

plantillas variadic son parte del estándar C ++ 0x que no se libere aún oficialmente. Ellos son apoyados por gcc desde la versión 4.3, pero hay que habilitar el soporte para C ++ 0x añadiendo el modificador de compilador -std = c ++ 0x.

Otros consejos

Uno de los ejemplos más simples posibles es la siguiente implementación de max que ni siquiera está en templated tipos.

int maximum(int n)
{
    return n;
}

template<typename... Args>
int maximum(int n, Args... args)
{
    return max(n, maximum(args...));
}

Sólo un poco más compleja es la aplicación canónica printf:

void printf(const char *s)
{
  while (*s)
  {
    if (*s == '%' && *(++s) != '%')
      throw "invalid format string: missing arguments";
    std::cout << *s++;
  }
}

template<typename T, typename... Args>
void printf(const char* s, T value, Args... args)
{
  while (*s)
  {
    if (*s == '%' && *(++s) != '%')
    {
      std::cout << value;
      printf(s, args...); // call even when *s == 0 to detect extra arguments
      return;
    }
    std::cout << *s++;
  }
  throw "extra arguments provided to printf";
}

plantillas variadic son una característica de C ++ 0x que se dirige principalmente a los autores de bibliotecas genéricas. Yo no esperaría verlos en "código de usuario". Por ejemplo, en el C ++ 0x biblioteca estándar que se utilizan en una gran cantidad de lugares: std :: función, std :: asíncrono, std :: reference_wrapper, std :: tupla, std :: packaged_task, ...

Para darle un ejemplo te voy a mostrar cómo un reference_wrapper podría ser implementado con respecto a las plantillas variadic:

template<class T>
class reference_wrapper
{
    T *ptr;
public:
    explicit reference_wrapper(T& thing) : ptr(&thing) {}
    explicit reference_wrapper(T&&     ) = delete;

    operator T&() const {return *ptr;}

    template<class... Args>
    decltype( declval<T&>()(declval<Args>()...) )
    operator()(Args&&... args) const
    {
        return (*ptr)(forward<Args>(args)...);
    }
};

Esto no es conforme a la perfección el proyecto de norma, pero se supone que es compilar con muy pocas modificaciones. Demuestra múltiple C ++ 0x características:

  • funciones eliminados (deshabilitar el constructor para rvalues)
  • referencias rvalue (detección de argumentos rvalue al constructor, el reenvío perfecto)
  • Tipo de deducción a través de decltype
  • estándar declval plantilla de función de biblioteca para crear objetos con el propósito de construir una expresión para decltype (CCG todavía no ofrece esta plantilla de función. Tienes que escribir tu mismo)
  • plantillas variadic (aceptando un número arbitrario de parámetros)

El propósito de la plantilla miembro variadic es reenviar argumentos para el objeto a que se refiere por ptr. Esto debería funcionar en caso de que T es un tipo de puntero de función o un tipo de clase con el operador de llamada de función sobrecargada.

¡Salud! s

Un ejemplo muy simple de plantilla variadic:

Supongamos que desea tener una función que toma un número variable de argumentos y los mercado digital. Por ejemplo:

print("Hello", 1, 3.14, 5L);

Para que la funcionalidad de trabajo, se requeriría, en esencia dos funciones:

primera, una función que toma número variable de argumentos:

template<typename T, typename... Args>
void print(T t, Args ...args){
     std::cout << t << ", ";
     print(args...);
}

Algunas explicaciones:

1.) Los paquetes de parámetros indicados por puntos suspensivos (...), que aparecen en la lista de parámetros.

typename...Args 
        |  | << Optional whitespace. Can have multiple whitespaces in between them
    Args...args

Eso significa, todos éstos son los mismos.

typename ...args
typename...args
typename   ...   args

Por lo tanto, usted no tiene que preocuparse por la posición correcta de los espacios en blanco en ese país. Sin embargo, la OMI como máximo un espacio en blanco se debe utilizar como una buena práctica.

2) Disco de expansión:. Un patrón seguido por una elipsis

.
print(args...); //expand when you wish to use them

3.) Paquete parámetro acepta cero o más args plantilla. Por lo tanto, acepta print(T t, Args... args) una o más args.


Una vez que entienda que, podemos visualizar el flujo de llamadas de la siguiente manera:

print("Hello", 1, 3.14, 5L);

se traduce en:

print(string, int, float, long);

, que las llamadas

print(int, float, long);

, que las llamadas

print(float, long);  // say Level 2

, que las llamadas

print(long);         // say Level 1

, que las llamadas

print();             // say Level 0

Si ha seguido el punto # 3 con cuidado, usted debe haber dado cuenta de que print(T t, Args... args) no puede manejar la llamada en el Nivel 0.
Así que tenemos aquí otra función con el mismo nombre para ponerse al día en cualquier nivel de> = 0.


segunda, una función para Horquilla la llamada en la parte superior de la pila de llamadas

Catch en el nivel 0:

void print(){}

o, Captura en el nivel 1:

template<typename T>
void print(T t){ std::cout << t;}

o, Captura a nivel 2:

template<typename T, typename U>
void print(T t, U u){ std::cout << t << ", " << u;}

así sucesivamente ...

Cualquiera de ellos podría funcionar. Espero que esto ayude próxima vez que vaya a escribir dicha función o clase.

Este es un ejemplo de las plantillas variadic que pongo en mi blog: http://thenewcpp.wordpress.com/2011/ 11/23 / variadic-plantillas-parte-1-2 /

Se compila. Demuestra encontrar el tipo más grande de un grupo de tipos.

#include <type_traits>

template <typename... Args>
struct find_biggest;

//the biggest of one thing is that one thing
template <typename First>
struct find_biggest<First>
{
  typedef First type;
};

//the biggest of everything in Args and First
template <typename First, typename... Args>
struct find_biggest<First, Args...>
{
  typedef typename find_biggest<Args...>::type next;
  typedef typename std::conditional
  <
    sizeof(First) >= sizeof(next),
    First,
    next
  >::type type;
};

Antes de C ++ 11, puede crear plantilla sólo con el recuento fijo de parámetros.

plantilla Firts para la función con un parámetro.

En segundo lugar plantilla para la función con dos parámetros. Es decir ....

Como C ++ 11 se puede escribir sólo una plantilla, compilador generará función requerida en sí.

El buen ejemplo http://eli.thegreenplace.net/2014/variadic-templates-in- c /

otra sintaxis:. Expansión, por ejemplo

template<typename VAL, typename... KEYS>
class MyMaps
{
  typedef std::tuple< std::map<KEYS,VAL>... > Maps;
}

por lo tanto:

MyMaps<int,int,string>:Maps

es ahora en realidad:

std::tuple<std::map<int,int>,std::map<string,int> >
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top