Pergunta

Eu estou usando libgc, um coletor de lixo para C e C ++. Para fazer contêineres STL lixo um colecionável deve usar o gc_allocator.

Em vez de escrever

std::vector<MyType> 

tem de se escrever

std::vector<MyType,gc_allocator<MyType> >

Poderia haver uma maneira de definir algo como

template<class T> typedef std::vector<T,gc_allocator<T> > gc_vector<T>;

Eu verifiquei há algum tempo e descobri que não era possível. Mas pode ter sido errado ou pode haver outro caminho.

A definição de mapas dessa forma é particularmente desagradável.

std::map<Key,Val> 

se torna

std::map<Key,Val, std::less<Key>, gc_allocator< std::pair<const Key, Val> > >

EDIT: Depois de tentar o uso de macro eu descobri os seguintes intervalos de código-lo:

#define gc_vector(T) std::vector<T, gc_allocator<T> >
typedef gc_vector( std::pair< int, float > ) MyVector;

A vírgula dentro da definição de tipo templated é interpretado como um separador de argumentos macro.

Assim, parece que a classe interna / struct é a melhor solução.

Aqui está um exemplo de como isso será feito em 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; 
Foi útil?

Solução

Você pode usar o C ++ 11 templated tipo aliasing usando using por exemplo como esta

template <typename T>
using gc_vector = std::vector<T, gc_allocator<T>>;

. Nota: Eu sei que isto é uma questão de idade, mas já que tem bastante muitos upvotes e como se vê nos resultados de pesquisa achei que merecia uma resposta atualizada

Outras dicas

Você não pode usar uma "typedef templated", mas você pode usar uma classe de conveniência / struct com um tipo interno:

template<typename T>
struct TypeHelper{
    typedef std::vector<T,gc_allocator<T> > Vector;
};

e, em seguida, usar em seu código

TypeHelper<MyType>::Vector v;
TypeHelper<MyType>::Vector::iterator it;

E algo semelhante para o mapa:

template<typename K,typename V>
struct MapHelper{
    typedef std::map<K, V, gc_allocator<K,V> > Map;
};

EDIT - @Vijay: Eu não sei se há outra solução possível, é assim que eu iria fazê-lo; uma macro pode dar-lhe uma notação mais compacta, mas pessoalmente eu não iria gostar:

#define GCVECTOR(T) std::vector<T,gc_allocator<T> >
!

EDIT - @chmike: nota por favor que a solução TypeHelper não requer que você redefinir construtores

Você pode publicamente herdar:

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
};

Isto resolve o problema completamente. O tipo derivado pode ser usado em todos os lugares onde o tipo de base pode ser usada, e não há nenhuma sobrecarga de implementação com qualquer compilador decente.

O fato de que std :: vector tem destrutor não-virtual pode levar a um comportamento indefinido acordo com o padrão C ++ se você tentar excluir uma variável de classe derivada através de um ponteiro para variável de classe base.

No mundo real isso não deve importar neste caso em particular - a classe derivada tem nada de novo acrescentado em comparação com a classe base e, portanto, o destruidor para a classe derivada apenas chama o destruidor para a classe base. Prossiga com a paranóia, a porta cuidadosamente qualquer maneira.

Se você nunca alocar esses variáveis ??de classe no montão (e é típico para alocar variáveis ??vetor na pilha e como membros de outras classes), o problema destructor não-virtual não afetá-lo.

Isso pode ser feito com uma macro, se você estiver disposto a empurrar o seu compilador para os seus limites. Eu fiz isso durante a implementação equivalentes C ++ para classes "Future" e "resgatáveis" do Java. Nossos objetos contados-referência usa biblioteca, tão "Referência " é em si uma classe de modelo em que "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>>

A beleza desta é que é que a macro faz exatamente o que você quer de um "typedef modelo", as desvantagens é que você não pode usar "<>" para o seu parâmetro de tipo (s) e não há nenhum tipo de inferência.

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) { .... }
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top