Подтвердить что ты не робот

Шаблонный typedef?

Я использую libgc, сборщик мусора для C и С++. Чтобы сборщик контейнеров STL собирался, нужно использовать gc_allocator.

Вместо записи

std::vector<MyType> 

нужно написать

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

Может ли быть способ определить что-то вроде

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

Я проверил некоторое время назад и выяснил, что это невозможно. Но я, возможно, ошибался, иначе может быть другой путь.

Определение карт таким образом особенно неудобно.

std::map<Key,Val> 

становится

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

EDIT: после попытки использования макроса я обнаружил, что следующий код разрывает его:

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

Запятая в определении шаблонного типа интерпретируется как разделитель макросов.

Итак, кажется лучшим внутренним классом/структурой.

Вот пример того, как это будет сделано в С++ 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; 
4b9b3361

Ответ 1

Вы не можете использовать "templated typedef", но вы можете использовать класс удобства/структуру с внутренним типом:

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

а затем используйте в своем коде

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

И что-то подобное для карты:

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

EDIT - @Vijay: Я не знаю, есть ли другое возможное обходное решение, как я это сделаю; макрос может дать вам более компактную нотацию, но лично мне это не понравится:

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

EDIT - @chmike: Обратите внимание, что решение TypeHelper не требует переопределения конструкторов!

Ответ 2

Вы можете использовать сглаживание типа С++ 11 с использованием using, например. как это

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

Примечание. Я знаю, что это старый вопрос, но поскольку он имеет довольно много оборотов и, как он появляется в результатах поиска, я думал, что он заслуживает обновленного ответа.

Ответ 3

Вы можете публично наследовать:

template<class T>
class gc_vector<T> : public std::vector<T, gc_allocator<T> >
{
    public:
    // You'll have to redeclare all std::vector constructors here so that
    // they just pass arguments to corresponding constructors of std::vector
};

Это полностью решает вашу проблему. Полученный тип можно использовать везде, где может использоваться базовый тип, и нет никаких накладных расходов на реализацию с любым достойным компилятором.

Тот факт, что std::vector имеет не виртуальный деструктор, может привести к поведению undefined в соответствии со стандартом С++, если вы попытаетесь удалить переменную производного класса с помощью указателя на переменную базового класса.

В реальном мире это не имеет значения в данном конкретном случае - производный класс не имеет ничего нового добавленного по сравнению с базовым классом, и поэтому деструктор для производного класса просто вызывает деструктор для базового класса. Действуйте с паранойей, порт осторожно в любом случае.

Если вы никогда не выделяете эти переменные класса в кучу (и это типично для распределения векторных переменных в стеке и как члены других классов), проблема не виртуального деструктора не влияет на вас.

Ответ 4

Это можно сделать с помощью MACRO, если вы готовы подтолкнуть свой компилятор к своим пределам. Я сделал это, реализуя эквиваленты С++ для классов Java "Future" и "Callable". В нашей библиотеке используются объекты с подсчетом ссылок, поэтому "Ссылка <T> " сам является классом шаблона, где "T" происходит от "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>>

Красота этого заключается в том, что макрос делает именно то, что вы хотите от "шаблона typedef", а нижние - тем, что вы не можете использовать "< > " для вашего параметра (ов) и там нет вывода типа.

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) { .... }