2008-11-09 9 views
23

C++ 0x permitirá que la plantilla tome un número arbitrario de argumentos. ¿Cuál es el mejor uso de esta función aparte de implementar tuplas?Plantillas variables

Respuesta

33
  1. de tipo seguro printf
  2. Transmisión de arbitrarias muchos argumentos de constructor en métodos de fábrica
  3. Tener arbitrario clases base permite poner y eliminar políticas útiles.
  4. Inicializando moviendo objetos de tipo heterogéneo directamente en un contenedor con un constructor de plantilla variado.
  5. Tener un operador literal que puede calcular un valor para un literal definido por el usuario (como "10110b").

Muestra a 3:

template<typename... T> struct flexible : T... { flexible(): T()... { } }; 

Muestra a 4:

struct my_container { template<typename... T> my_container(T&&... t) { } }; 
my_container c = { a, b, c }; 

Muestra a 5:

template<char... digits> 
int operator "" b() { return convert<digits...>::value; } 

ver este código de ejemplo: here

+0

no solo impresión segura de tipos, sino funciones variadas seguras de tipo? –

2
  • de tipo seguro printf
+0

Sí, pero aún tengo que ver una implementación muy elegante de eso :-) –

+0

I thi nk este ejemplo específico es algo así como un caso degenerado. Recuerde que para cada instanciación, el compilador necesita crear más código. ¿Te imaginas crear más de 100 versiones de printf por cada posible combinación de argumentos utilizada? Oh el infierno! – shoosh

+2

@Shy: no si todas las versiones son envolturas en línea para la impresión * real *. – CesarB

2

Permitir cosas como Boost.Function a tomar un número arbitrario de parámetros

2

Acabo de escribir un article sobre cómo implementar múltiples interfaces COM y mantener su código compacto y elegante con las plantillas variables de C++ 0x.

0

Escriba la seguridad de cada llamada con número de argumento dinámico.

+0

¿Podría ser más preciso? – alestanis

1

He implementado un NDArray (matriz N-dimensional) y tiene el método setSizes con varios recuentos de argumentos. Usar argumentos de plantilla variadic es más seguro que usar argumentos de funciones variadic, además puedo controlar el recuento de parámetros pasados ​​a esta función en tiempo de compilación solo con argumentos de plantillas variadic.

void setSizes(uintmax_t currentSize) { 
    static_assert(1 == NDimensions, "Invalid count of arguments given to setSizes."); 

    size_ = currentSize; 
    data_ = new NDArrayReferenceType[currentSize]; 
} 

template <typename... Sizes> 
void setSizes(uintmax_t currentSize, Sizes... sizes) { 
    static_assert(sizeof...(Sizes) + 1 == NDimensions, "Invalid count of arguments given to setSizes."); 

    size_ = currentSize; 
    data_ = new NDArrayReferenceType[currentSize]; 

    for (uintmax_t i = 0; i < currentSize; i++) { 
     data_[i]->setSizes(sizes...); 
    } 
} 

También he implementado un envoltorio de constructor universal para mi SmartPointer hecho a sí mismo. Se ajusta a todo constructor definido por el usuario del tipo de puntero sin formato.

template <typename TSmartPointer, typename... Args> 
static inline void initialize(TSmartPointer *smartPointer, Args... args) { 
    smartPointer->pointer_ = new typename TSmartPointer::PointerType(std::forward<Args>(args)...); 
    smartPointer->__retain(); 
} 

Este código parece ser inobvious, esto es una parte de la inicialización de la SmartPointer para el caso si SmartPointer debe llamar automáticamente al constructor del puntero en la adquisición de la SmartPointer (RAII). En el caso de las clases abstractas, no puede llamar al constructor.

Por lo tanto, si tengo una AbstractObject tipo, que es SmartPointer de una clase abstracta, y el tipo ConcreteObject, que es SmartPointer de la clase con el constructor que toma dos enteros, puedo escribir código siguiente:

AbstractObject object = ConcreteObject(42, 42); 

es como C# y Java (pero con RAII) y funciona para mí en C++/GCC 4,8 =)

3

Tal vez la charla por Andrei Alexandrescu en el caso Going Native 2012, será de su interés:

Here es el video eo y Here la documentación.

0

La impresión segura de tipos se ha mencionado en otras respuestas, pero en general se pueden usar plantillas variadas para implementar funciones de formateo que no requieren pasar información de tipo a través de especificadores de formato. Por ejemplo, los C++ Format library implementos formatear funciones similares a Python de str.format:

fmt::print("I'd rather be {1} than {0}.", "right", "happy"); 

además de printf seguro. Los tipos de argumentos se capturan automáticamente utilizando plantillas variadic en C++ 11.

Esto hace especificadores printf como lld o notoria PRIdPTR innecesaria y en lugar de

std::printf("Local number: %" PRIdPTR "\n\n", someIntPtr); 

uno puede simplemente utilizar

fmt::printf("Local number: %d\n\n", someIntPtr); 

Negación: Soy el autor de esta biblioteca

Cuestiones relacionadas