0

私はこのようないくつかのコードを持っています:

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

ファクトリ配列を 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」を簡単に実装し、「FactoryProduct<>::factory」に関する FooFactoryTable の知識を隠すことができるように

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 に答える