c++ - tipos - typedef struct uso
templado typedef? (4)
No puede usar un "tipo de letra con plantilla", pero puede usar una clase / estructura de conveniencia con un tipo interno:
template<typename T>
struct TypeHelper{
typedef std::vector<T,gc_allocator<T> > Vector;
};
y luego usar en tu código
TypeHelper<MyType>::Vector v;
TypeHelper<MyType>::Vector::iterator it;
Y algo similar para el mapa:
template<typename K,typename V>
struct MapHelper{
typedef std::map<K, V, gc_allocator<K,V> > Map;
};
EDITAR - @Vijay: No sé si hay otra solución posible, así es como lo haría; una macro puede darte una notación más compacta, pero personalmente no me gustaría:
#define GCVECTOR(T) std::vector<T,gc_allocator<T> >
EDITAR - @chmike: ¡tenga en cuenta que la solución TypeHelper
no requiere que redefina los constructores!
Estoy usando libgc, un recolector de basura para C y C ++. Para hacer que los contenedores STL sean coleccionables, se debe usar gc_allocator.
En lugar de escribir
std::vector<MyType>
uno tiene que escribir
std::vector<MyType,gc_allocator<MyType> >
¿Podría haber una manera de definir algo así como
template<class T> typedef std::vector<T,gc_allocator<T> > gc_vector<T>;
Lo revisé hace un tiempo y descubrí que no era posible. Pero puedo haber estado equivocado o podría haber otra forma de evitarlo.
Definir mapas de esta manera es particularmente desagradable.
std::map<Key,Val>
se convierte
std::map<Key,Val, std::less<Key>, gc_allocator< std::pair<const Key, Val> > >
EDITAR: Después de probar el uso de la macro, descubrí que el siguiente código la rompe:
#define gc_vector(T) std::vector<T, gc_allocator<T> >
typedef gc_vector( std::pair< int, float > ) MyVector;
La coma dentro de la definición de tipo de plantilla se interpreta como un separador de macro argumentos.
Entonces parece que la clase / estructura interna es la mejor solución.
Aquí hay un ejemplo de cómo se hará en C ++ 0X
// standard vector using my allocator
template<class T>
using gc_vector = std::vector<T, gc_allocator<T> >;
// allocates elements using My_alloc
gc_vector <double> fib = { 1, 2, 3, 5, 8, 13 };
// verbose and fib are of the same type
vector<int, gc_vector <int>> verbose = fib;
Puede usar el aliasing de tipo de plantilla de C ++ 11 usando using
ejemplo, como este
template <typename T>
using gc_vector = std::vector<T, gc_allocator<T>>;
Nota: Sé que esta es una pregunta antigua, pero como tiene muchos votos ascendentes y aparece en los resultados de búsqueda, pensé que merecía una respuesta actualizada.
Puedes heredar públicamente:
template<class T>
class gc_vector<T> : public std::vector<T, gc_allocator<T> >
{
public:
// You''ll have to redeclare all std::vector''s constructors here so that
// they just pass arguments to corresponding constructors of std::vector
};
Esto resuelve tu problema por completo. El tipo derivado se puede usar en todas partes donde se puede usar el tipo base, y no hay sobrecarga de implementación con ningún compilador decente.
El hecho de que std :: vector tenga un destructor no virtual podría llevar a un comportamiento indefinido de acuerdo con el estándar de C ++ si alguna vez intentas eliminar una variable de clase derivada mediante un puntero a la variable de la clase base.
En el mundo real esto no debería importar en este caso particular: la clase derivada no tiene nada nuevo agregado en comparación con la clase base y, por lo tanto, el destructor para la clase derivada solo llama al destructor para la clase base. Proceda con paranoia, puerto con cuidado de todos modos.
Si nunca asigna estas variables de clase en el montón (y es típico asignar variables vectoriales en la pila y como miembros de otras clases), el problema del destructor no virtual no le afecta.
Se puede hacer con un MACRO, si está dispuesto a llevar su compilador al límite. Lo hice al implementar C ++ equivalentes para las clases "Futuro" y "Invocable" de Java. Nuestra biblioteca utiliza objetos contados por referencia, por lo que "Referencia <T>" es en sí misma una clase de plantilla donde "T" deriva de "ReferencedObject".
1. Create your template Classes. Mine are:
template<typename T>
class Callable {
private:
public:
virtual T Call() = 0;
};
template<typename T> CountedFuture : public ReferencedObject {
private:
Callable<T>* theTask;
T theResult;
public:
T Get() {
// Run task if necessary ...
if(task) {
theResult = theTask->Call();
delete theTask;
}
return theResult;
}
};
2. In the application code I''m using references, so I define the macro:
#define Future(T) Reference<CountedFuture<T>>
La belleza de esto es que Macro hace exactamente lo que usted querría de una "plantilla typedef", las desventajas son que no puede usar "<>" para su tipo de parámetro (s) y no hay inferencia de tipo .
3. I can now use the Macro wherever I would use a template, like in functions:
Future(char*) DoSomething() { ... }
bool TestSomething(Future(std::string) f) { .... }