2013-10-02 5 views
0

У меня есть некоторый код, как это:есть ли альтернативы 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 максимально простым.

+0

Да, см. Boost mpl. По сути, он использует цепочки пар, чтобы заменить variardics, и макросы, чтобы создать небольшую псевдо-вариацию. Сколько типов мы говорим? Есть и другие подходы. – Yakk

+3

В качестве сторонних, если вы говорите о «других компиляторах», это GCC и Clang. Их поддержка новых функций C++ обычно намного превосходит VC++. Шаблоны Variadic, например, были в GCC с 4.3 и в Clang с 2.9, с тех пор оба они выпустили несколько стабильных версий. – us2012

+0

@ us2012 GCC? Позвольте мне процитировать их: «В реализации стандартной библиотеки GCC чрезмерное время компиляции вынуждало возвращать максимальное количество поддерживаемых параметров от исходного двадцати до десяти - наименьшее значение, разрешенное проектом стандарта [10].» (Jot.fm/issues/issue_2008_02/article2) « –

ответ

2

Используйте VS2013 RC. Он поддерживает вариационные шаблоны. Как и все компиляторы, ориентированные на другие текущие мобильные платформы.

Не работайте с неподдерживаемыми функциями, вы просто получите неприятные хаки, которые точно не делают то, что вы хотели.

0

Visual Studio поддерживает шаблоны «faux» и допускает до 5-10 (8 по умолчанию) аргументов. Вы можете использовать Variadics с VS2012, если вам действительно не нужно создавать шаблоны с множеством аргументов типа.

Смежные вопросы