Pregunta

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

¿Fue útil?

Solución

  1. Tipo de impresión segura
  2. Reenvío de argumentos arbitrarios de muchos constructores en métodos de fábrica
  3. Tener clases base arbitrarias permite poner y quitar políticas útiles .
  4. Inicializando moviendo objetos mecanografiados heterogéneos directamente a un contenedor al tener un constructor de plantilla variable.
  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; }

Vea este código de ejemplo: aquí

Otros consejos

Quizás la charla de Andrei Alexandrescu sobre el evento Going Native 2012 sea de su interés:

Aquí es el video y Aquí la documentación.

  • Tipo seguro printf

Permitir que cosas como Boost.Function tomen números arbitrarios de parámetros

Acabo de escribir un artículo sobre cómo implementar múltiples interfaces COM y mantener su código compacto y elegante con plantillas variadas C ++ 0x.

He implementado un NDArray (matriz N-dimentional) y tiene el método setSizes con recuento variado de argumentos. El uso de argumentos de plantilla variadic es más seguro que el uso de argumentos de función variadic, además, puedo controlar el recuento de parámetros pasados ??a esta función en tiempo de compilación solo con argumentos de plantilla 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 contenedor de constructor universal para mi SmartPointer hecho a sí mismo. Se ajusta sobre 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 no ser obvio, esto es parte del inicializador del SmartPointer para el caso de que SmartPointer llame automáticamente al constructor del puntero en la adquisición del SmartPointer (RAII). En el caso de clases abstractas, no puede llamar al constructor.

Entonces, si tengo un tipo AbstractObject, que es SmartPointer de una clase abstracta, y el tipo ConcreteObject, que es SmartPointer de clase con un constructor que toma dos ints, puedo escribir el siguiente código:

AbstractObject object = ConcreteObject(42, 42);

Es como C # y Java (pero con RAII) y funciona para mí en C ++ / GCC 4.8 =)

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

La impresión de tipo seguro se ha mencionado en otras respuestas, pero en general se pueden usar plantillas variadas para implementar funciones de formato que no requieren pasar información de tipo a través de especificadores de formato. Por ejemplo, la biblioteca de formato C ++ implementa funciones de formato similares a las de Python str.format :

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

además de impresión segura f. Los tipos de argumentos se capturan automáticamente utilizando plantillas variadas en C ++ 11.

Esto hace que los especificadores de printf como lld o notorious PRIdPTR sean innecesarios y en lugar de

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

uno simplemente puede usar

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

Descargo de responsabilidad : soy el autor de esta biblioteca

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top