为什么仅对功能模板使用模板参数推导/替换失败?

时间:2018-10-26 13:00:07

标签: c++ variadic-templates

我正在尝试一个类,它是多个模块的包装。每个模块都需要一些配置。我尝试使用可变参数模板函数来解决此问题,以确保在编译时应生成的每个模块都具有给定的配置数据。

剩下的唯一问题是我的创建函数模板的模板参数推导/替换失败。如果整个包装器都是模板化类,那么它将起作用。

下面,我将提供有关此问题的一些示例。我试图使它尽可能简单。

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

以下是coliru的示例:https://coliru.stacked-crooked.com/a/744c58c7025c1c2f

我开始怀疑我的c ++知识...

2 个答案:

答案 0 :(得分:3)

没有解释的解决方案,因为前一个解决方案是不正确的,stil挖...


您可以通过使FactoryConfig仅继承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; }
};

答案 1 :(得分:1)

在clang下编译正常,可能是gcc中的错误?参见g++ c++17 class template argument deduction not working in a very specific case,以获取类似的示例。