1

I'm experimenting with a class which is a wrapper of multiple modules. Each module needs some configuration. I try to solve this with a variadic template functions to ensure at compiletime, that each module which should be generated has it's configuration data given.

The only problem left is that the template argument deduction/substitution is failing for my creation function template. If the whole wrapper would be a templated class it would work.

Following I'm providing a little example of the problem. I tried to keep it as simple as possible.

class ClassA{};
class ClassB{};

template<class Module>
class FactoryModuleConfig;

template<>
class FactoryModuleConfig<ClassA>{
    public:
    FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    virtual ~FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
template<>
class FactoryModuleConfig<ClassB>{
    public:
    FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    virtual ~FactoryModuleConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

template< class... Args >
class FactoryConfig;

template<class Arg, class... Args>
class FactoryConfig<Arg, Args...> : public FactoryModuleConfig<Arg>, public virtual FactoryConfig<Args...>
{
    public:
        FactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
        virtual ~FactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

template<>
class FactoryConfig<>
{
    public:
        FactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
        virtual ~FactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
};

class myFactoryConfig : public FactoryConfig<ClassA,ClassB>{
 public: 
    myFactoryConfig(){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    virtual ~myFactoryConfig( ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
    int getNumberOfModules() const { return 1; } 
};

class Factory{
        Factory(){}
    public:
        virtual ~Factory(){}

        template<class ...Args>
        static Factory* create(FactoryConfig<Args...>* pCfg){ return new Factory();}
};

template<class ...Args>
class Factory2{
    public:
        Factory2(FactoryConfig<Args...>* pCfg){}
        virtual ~Factory2(){}
};

int main()
{
    // Solution 1
    myFactoryConfig* pCfg = new myFactoryConfig();                      // <-- why is this not working 
    // FactoryConfig<ClassA,ClassB>* pCfg = new myFactoryConfig();      // <-- and this works like a charm
    Factory* pfac = Factory::create<ClassA,ClassB>(pCfg);

    // Solution 2                                                       // Solution 2 is always working
    //FactoryConfig<ClassA,ClassB>* pCfg = new myFactoryConfig();       
    //Factory2<ClassA,ClassB>* pfac = new Factory2<ClassA,ClassB>(pCfg);  

    delete pfac;
    delete pCfg;

    return 0;
}

Here is the example at coliru: https://coliru.stacked-crooked.com/a/744c58c7025c1c2f

I'm starting to doubt my c++ knowledge...

theBro
  • 66
  • 5
  • `new Factory2` succeeds because *there isn't deduction*, you *must* specify all the parameters for the class template, so there can't be trailing `Args...` – Caleth Oct 26 '18 at 13:48

2 Answers2

3

Solution without explanation as the previous one was incorrect, stil digging...


You can solve this by making FactoryConfig only inherits FactoryModule<>:

template< class... Args >
class FactoryConfig: public FactoryModuleConfig<Args>...
{
    public:
        FactoryConfig() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
        virtual ~FactoryConfig() { std::cout << __PRETTY_FUNCTION__ << std::endl; }
};
Holt
  • 36,600
  • 7
  • 92
  • 139
1

Compiles fine under clang, possibly a bug in gcc? See g++ c++17 class template argument deduction not working in a very specific case for a vaguely similar example.