Шаблонный 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;
Ответы
Ответ 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) { .... }