0

我有一些这样的代码:

// 工厂.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);
    }
};

为了向 init FactoryTable<> 提供工厂数组,我必须在 FooFactoryTable 中手动创建一个数组 (IFactory* table[])。所以我使用可变参数模板来避免这种情况:

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<>::factory”的知识

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尽可能的简单。

4

2 回答 2

2

使用 VS2013 RC。它支持可变参数模板。所有针对其他当前移动平台的编译器也是如此。

不要绕过不受支持的功能,你最终会遇到不完全符合你想要的讨厌的黑客攻击。

于 2013-10-02T11:48:46.177 回答
0

Visual Studio 确实支持“人造”可变参数模板,并允许多达 5-10 个(默认为 8 个)参数。您可以在 VS2012 中使用可变参数,除非您确实需要使用大量类型参数来实例化模板。

于 2013-10-02T23:55:47.550 回答