0

i have some code like this:

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

in order to provide a factory array to init FactoryTable<>, i have to manually create an array (IFactory* table[]) in FooFactoryTable. so i use variadic template to avoid this:

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

so that i can simply implement "FooFactoryTable" like this, and hide FooFactoryTable's knowledge about "FactoryProduct<>::factory"

class FooFactoryTable : public FactoryTable<FooFactoryTable, BaseFoo, 
    Foo1,
    Foo2> {};

my question is, is there another way to implement "FactoryTable" without using variadic template? because variadic template is not supported by visual studio 2012(v110), and "'Microsoft Visual C++ Compiler Nov 2012 CTP' is for testing purposes only.". i worry other compilers may also have the same problem as visual studio 2012(v110). the "other compilers" is those compilers that targeting android or iphone.

note that: the main reason for re-implementing "FactoryTable" is to make FooFactoryTable as simpler as possible.

autumn
  • 172
  • 1
  • 1
  • 10
  • Yes, see boost mpl. In effect, it uses chained pairs to replace variardics, and macros to create small pseudo variardics. How many types we talking? There are other approaches as well. – Yakk - Adam Nevraumont Oct 02 '13 at 10:28
  • 3
    As an aside, if those "other compilers" you are speaking of are GCC and Clang - their support for new C++ features is usually superior by far to VC++'s. Variadic templates for example have been in GCC since 4.3 and in Clang since 2.9, they both have released multiple stable versions since. – us2012 Oct 02 '13 at 10:34
  • @us2012 GCC? Let me quote them: "In the GCC standard library implementation, excessive compilation times forced reverting the maximum number of supported parameters from the original twenty to ten—the smallest value allowed by the draft standard [10]. " (jot.fm/issues/issue_2008_02/article2)" – Ark-kun Oct 02 '13 at 23:57
  • @us2012 VS2012 supports the same 10 type arguments as GCC 4.3. GCC couldn't have correct variadics support since the variadics standard changed rather recently (too late for Visual Studio 2012 release). The final C++11 standard was released in the middle of 2011. – Ark-kun Oct 02 '13 at 23:59
  • @Ark-kun do you mean: if i want unlimited count(at least UINT8_MAX) of type arguments, i may not use variadic templates. even if the compiler does support variadic templates, the compilation time may be too long. what about gcc4.8 or 4.7.x? – autumn Oct 03 '13 at 08:11
  • I doubt any compiler would be able to compile unfinite-templated code. If you want to INSTANTIATE (not just declare) variadic template with more than 10 types, your only option is to wait 1-2 months for the final Visual Studio 2013 release or use the latest GCC versions. Looks like the VS2012 november compiler fixes won't be in VS2012 updates (http://connect.microsoft.com/VisualStudio/feedback/details/783189/codename-milan-new-c-features-still-missing-in-vs-2012-update-2), but this needs checking. – Ark-kun Oct 03 '13 at 18:07
  • i have tried on both vs2012(Platform Toolset=v120_CTP_Nov2012) and android-ndk(arm-linux-androideabi-gcc-4.8) with the case that instantiate the template with 60 types, it works fine. so i think they may support large enough count of types, and stop test further. – autumn Oct 05 '13 at 16:44

2 Answers2

2

Use VS2013 RC. It supports variadic templates. As do all compilers targeting other current mobile platforms.

Don't work around unsupported features, you'll just end up with nasty hacks that don't exactly do what you wanted.

rubenvb
  • 74,642
  • 33
  • 187
  • 332
0

Visual Studio does support "faux" variadic templates and allows up to 5-10 (8 by default) arguments. You can use variadics with VS2012 unless you really need to instantiate templates with a lot of type arguments.

Ark-kun
  • 6,358
  • 2
  • 34
  • 70