从另一个模板类

时间:2017-04-20 10:37:10

标签: c++ templates c++14 decltype

我想在创建类T1,T2的实例时省略一些模板参数DeriveGenerator<T3,T4,T1,T2>以安慰我的生活。

以下是我遇到的最终简化版本。

我的图书馆: -

重要的部分是班级宣言。 (this line
 他们的内部内容只是一个填充物。

template<class T1,class T2>class BaseGenerator{ //<-- this line
    public: std::pair<T1*,T2*> generateBase(){ 
        /** actually create T3,T4 internally */
        return std::pair<T1*,T2*>(nullptr,nullptr);
    }
};
template<class T3,class T4,class T1,class T2>class DeriveGenerator{ //<-- this line
    public: Base<T1,T2>* base;
    public: std::pair<T3*,T4*> generateDerive(){ 
        auto pp=base->generateBase();
        return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
    }
};

用户: -

class B1{};class B2{};
class B3:public B1{};
class B4:public B2{};
int main() {
    //v this is what I have to
    BaseGenerator<B1,B2> baseGen;
    DeriveGenerator<B3,B4,B1,B2> deriveGen;  //so dirty #1
    deriveGen.base=&baseGen;
    deriveGen.generateDerive();
}

问题

是否可以使线#1更清洁?
我希望deriveGen 的类型取决于 baseGen的类型。

这是我的意愿: -

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4> deriveGen;   //<-- modified
deriveGen.base=&baseGen;

或至少类似: -

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4, DECLARATION_TYPE(baseGen) > deriveGen;   //<-- modified
deriveGen.base=&baseGen;

我已阅读(仍然没有线索): -

我甚至不知道是否可能。

decltype ”似乎是最接近的线索,但我无法找到将其应用于此案例的方法。
我想我可能要把它分成T1,T2 ....(?)

修改

在实际情况中,baseGen是某些类的非静态字段,尚未实例化,例如

class Holder{
    public: BaseGenerator<B1,B2> baseGen;
};

因此,在声明deriveGen时,我无法触及baseGen的实际情况。
这是困难的部分。

我可以通过baseGen引用decltype的类型 (抱歉没有提及)

3 个答案:

答案 0 :(得分:5)

如果您可以将DeriveGenerator定义更改为:

template<class T3, class T4, class BaseT>
class DeriveGenerator{
public:
    BaseT* base = nullptr;

    std::pair<T3*, T4*> generateDerive(){ 
        auto pp = base->generateBase();
        return {(T3*)(pp.first), (T4*)(pp.second)};
    }
};

您可以使用:

BaseGenerator<B1, B2> baseGen;
DeriveGenerator<B3, B4, decltype(baseGen)> deriveGen;

否则我建议创建一个帮手:

 template <typename B3, typename B4, typename B1, typename B2>
 DeriveGenerator<B3, B4, B1, B2>
 MakeDerived(BaseGenerator<B1, B2>& baseGen)
 {
     DeriveGenerator<B3, B4, B1, B2> deriveGen;
     deriveGen.base = &baseGen;
     return deriveGen;
 }

然后使用

BaseGenerator<B1,B2> baseGen;
auto deriveGen = MakeDerived<B3, B4>(baseGen);

答案 1 :(得分:2)

不确定你想要什么但是......我想你可以用这种方式定义DeriveGenerator

template <typename, typename, typename>
class DeriveGenerator;

template <typename T3, typename T4, typename T1, typename T2>
class DeriveGenerator<T3, T4, BaseGenerator<T1, T2>>
 {
   public:
      BaseGenerator<T1,T2>* base;

   public:
      std::pair<T3*,T4*> generateDerive ()
       { 
         auto pp=base->generateBase();
         return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
       }
 };

并按如下方式使用

BaseGenerator<B1,B2> baseGen;
DeriveGenerator<B3,B4,decltype(baseGen)> deriveGen; 

如果您对T1T2类型感兴趣,请执行此操作;如果您只对BaseGenerator<T1, T2>感兴趣,可以直接写

template <typename T3, typename T4, typename Tbase>
class DeriveGenerator
 {
   public:
      Tbase * base;

   public:
      std::pair<T3*,T4*> generateDerive ()
       { 
         auto pp=base->generateBase();
         return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
       }
 };

答案 2 :(得分:1)

我认为将T1的{​​{1}}和T2模板参数推送到实际的DeriveGenerator方法本身更简单:

generateDerive

Demo

现在你可以这样称呼它:

template<class T3,class T4>
class DeriveGenerator{ 
    public: 
    template<class T1, class T2, template<class, class> class Base>
    std::pair<T3*,T4*> generateDerive(Base<T1, T2>* base){
        static_assert(std::is_base_of<T1, T3>::value && std::is_base_of<T2, T4>::value, "T1 should be base of T3 and T2 should be base of T4"); 
        auto pp=base->generateBase();
        return std::pair<T3*,T4*>((T3*)(pp.first),(T4*)(pp.second));
    }
};

我向BaseGenerator<B1,B2> baseGen; DeriveGenerator<B3,B4> deriveGen; deriveGen.generateDerive(&baseGen); 添加了static_assert,确保使用std::is_base_of进行正确的基础/派生配对,这样如果您不小心搞砸了模板参数,就会遇到编译器错误。

DeriveGenerator::generateDerive