program - stl c++ español
Clase de plantilla con contenedor de plantilla (2)
¿Cómo puedo declarar la clase de plantilla (adaptador) con diferentes contenedores como argumentos de plantilla? Por ejemplo, necesito declarar clase:
template<typename T, typename Container>
class MyMultibyteString
{
Container buffer;
...
};
Y lo quiero basado en el vector. ¿Cómo hacer que sea difícil de definir? (para evitar que alguien escriba dicha declaración MyMultibyteString<int, vector<char>>
).
Además, cómo implementar tal construcción:
MyMultibyteString<int, std::vector> mbs;
sin pasar el argumento de la plantilla al contenedor.
Debe usar los parámetros de plantilla de plantilla :
template<typename T, template <typename, typename> class Container>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MyMultibyteString
{
Container<T, std::allocator<T>> buffer;
// ...
};
Esto te permitiría escribir:
MyMultibyteString<int, std::vector> mbs;
Aquí hay un ejemplo de compilación en vivo . Una forma alternativa de escribir lo anterior podría ser:
template<typename T,
template <typename, typename = std::allocator<T>> class Container>
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
class MyMultibyteString
{
Container<T> buffer; // <== No more need to specify the second argument here
// ...
};
Y aquí está el ejemplo en vivo correspondiente.
Lo único que debe prestar atención es que el número y tipo de argumentos en la declaración del parámetro de plantilla debe coincidir exactamente con el número y tipo de argumentos en la definición de la plantilla de clase correspondiente que desea pasar como argumento de plantilla, independientemente de del hecho de que algunos de esos parámetros pueden tener valores predeterminados.
Por ejemplo, la plantilla de clase std::vector
acepta dos parámetros de plantilla (el tipo de elemento y el tipo de asignador), aunque el segundo tiene el valor predeterminado std::allocator<T>
. Debido a esto, no podrías escribir:
template<typename T, template <typename> class Container>
// ^^^^^^^^
// Notice: just one template parameter declared!
class MyMultibyteString
{
Container<T> buffer;
// ...
};
// ...
MyMultibyteString<int, std::vector> mbs; // ERROR!
// ^^^^^^^^^^^
// The std::vector class template accepts *two*
// template parameters (even though the second
// one has a default argument)
Esto significa que no podrá escribir una sola plantilla de clase que pueda aceptar tanto std::set
como std::vector
como un parámetro de plantilla de plantilla, porque a diferencia de std::vector
, la plantilla de clase std::set
acepta tres parámetros de la plantilla .
Otro enfoque para resolver esto es mediante el uso de plantillas variadic y con eso puede usar cualquier contenedor como se sugiere en los comentarios anteriores y aquí está la implementación:
template<template <typename... Args> class Container,typename... Types>
class Test
{
public:
Container<Types...> test;
};
int main()
{
Test<std::vector,int> t;
Test<std::set,std::string> p;
return 0;
}