У меня есть некоторый код, как это:есть ли альтернативы VARIADIC шаблон
// Factory.h
typedef std::uint8_t FactoryId;
const FactoryId FACTORY_ID_MAX_VALUE = UINT8_MAX;
template <typename TBaseProduct>
class IFactory {
public:
virtual TBaseProduct* create() = 0;
};
template <typename TProduct, typename TBaseProduct>
class Factory : public IFactory<TBaseProduct> {
public:
virtual TBaseProduct* create() override {
return new TProduct;
}
};
template <typename TProduct, typename TBaseProduct>
class FactoryProduct : public TBaseProduct {
public:
static Factory<TProduct, TBaseProduct> factory;
};
template <typename TFactoryTable, typename TBaseProduct>
class FactoryTable {
public:
typedef IFactory<TBaseProduct> BaseFactory;
typedef BaseFactory* BaseFactoryPtr;
FactoryTable(): factorys(nullptr) {}
~FactoryTable() { delete[] factorys; }
BaseFactory& get(FactoryId factoryId) {
if (factoryId > maxFactoryId) {
throw std::exception("out of range");
}
return *factorys[factoryId];
}
protected:
template <std::size_t factoryCount>
void init(BaseFactoryPtr (&factorys)[factoryCount]) {
init(factorys, factoryCount);
}
void init(BaseFactoryPtr* factorys, std::size_t factoryCount) {
assert(factorys != nullptr);
assert(factoryCount > 0 && factoryCount - 1 <= FACTORY_ID_MAX_VALUE);
this->factorys = new BaseFactoryPtr[factoryCount];
std::memcpy(this->factorys, factorys, sizeof(BaseFactoryPtr) * factoryCount);
this->maxFactoryId = factoryCount - 1;
}
private:
BaseFactoryPtr* factorys;
FactoryId maxFactoryId;
};
// foo.h
class BaseFoo {};
class Foo1 : public FactoryProduct<Foo1, BaseFoo> {};
class Foo2 : public FactoryProduct<Foo2, BaseFoo> {};
class FooFactoryTable : public FactoryTable<FooFactoryTable, BaseFoo> {
public:
FooFactoryTable() {
IFactory<BaseFoo>* table[] = {
&Foo1::factory,
&Foo2::factory,
};
init(table);
}
};
для того, чтобы обеспечить завод array to init FactoryTable <>, мне нужно вручную создать массив (IFactory * table []) в FooFactoryTable. поэтому я использую VARIADIC шаблон, чтобы избежать этого:
template <typename TFactoryTable, typename TBaseProduct, typename... MTProduct>
class FactoryTable {
// the visible of the two init() is changed from protected to private.
// except this, the only changed member is the constructor
FactoryTable(): factorys(nullptr) {
IFactory<BaseFoo>* table[] = {
(&MTProduct::factory)...
};
init(table);
}
};
так, что я могу просто реализовать «FooFactoryTable», как это, и скрыть знание FooFactoryTable о «FactoryProduct <> :: завод»
class FooFactoryTable : public FactoryTable<FooFactoryTable, BaseFoo,
Foo1,
Foo2> {};
мой вопрос есть, есть ли другой способ реализовать «FactoryTable» без использования вариационного шаблона? потому что вариационный шаблон не поддерживается visual studio 2012 (v110), а «Microsoft Visual C++ Compiler Nov 2012 CTP» предназначен только для тестирования ». Я беспокоюсь, что другие компиляторы могут также иметь ту же проблему, что и visual studio 2012 (v110). «другие компиляторы» - это те компиляторы, которые нацелены на Android или iphone.
Обратите внимание, что: основная причина повторной реализации «FactoryTable» заключается в том, чтобы сделать FooFactoryTable максимально простым.
Да, см. Boost mpl. По сути, он использует цепочки пар, чтобы заменить variardics, и макросы, чтобы создать небольшую псевдо-вариацию. Сколько типов мы говорим? Есть и другие подходы. – Yakk
В качестве сторонних, если вы говорите о «других компиляторах», это GCC и Clang. Их поддержка новых функций C++ обычно намного превосходит VC++. Шаблоны Variadic, например, были в GCC с 4.3 и в Clang с 2.9, с тех пор оба они выпустили несколько стабильных версий. – us2012
@ us2012 GCC? Позвольте мне процитировать их: «В реализации стандартной библиотеки GCC чрезмерное время компиляции вынуждало возвращать максимальное количество поддерживаемых параметров от исходного двадцати до десяти - наименьшее значение, разрешенное проектом стандарта [10].» (Jot.fm/issues/issue_2008_02/article2) « –