C++ 如何扩展模板以使用矢量<T>

C++ How to extend a template to work with vector<T>

本文关键字:lt gt 何扩展 扩展 C++      更新时间:2023-10-16

不幸的是,我的实际模板充满了与我的问题无关的东西,所以我试图将所有内容放在一个简短的例子中。比方说,我写了以下模板:

#include <vector>
template <typename T> class MyTemplate{
  public:
    typedef void(*MyFunc)(T);
    void addFunc(MyFunc f){myFuncs.push_back(f);}
    void callFuncs(T value){
        for (std::size_t i=0;i<myFuncs.size();i++){myFuncs[i](value);}
    }
  private:
    std::vector<MyFunc> myFuncs;
};

我已经了解到,当传递的类型是向量时,我可以专门化这个模板以使其表现不同,所以我写了这个:

template <typename T> class MyTemplate<std::vector<T> > {
   public:
       typedef void(*MySingleElementFunc)(T);
       void addSingleElementFunc(MySingleElementFunc f){
           this->mySingleElementFuncs.push_back(f);
       }
       void callFuncs(std::vector<T> value){
           //for (std::size_t i=0;i<myFuncs.size();i++){
           //    myFuncs[i](value);
           //}
           for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
               for (int size_t i=0;i<value.size();i++){
                    mySingleElemetnFuncs[i](value[i]);
               }
           }
       }       
       private:
           std::vector<MySingleElementFunc> mySingleElementFuncs;
};

现在我的问题是,最优雅的方法是什么(如果可能的话没有继承)不仅要针对向量的情况专门化模板而且同时仍然能够使用第一个模板方法,其中向量是模板参数。我稍后想做的是以下内容

void Func1(int i){}
void Func2(std::vector<int> i){}
MyTemplate<std::vector<int> > myTemplate;
myTemplate.addFunc(Func1);
myTemplate.addFunc(Func2);

是否可以在不简单地从原始模板复制和粘贴我需要的所有内容的情况下实现这一点,对专用版本也做同样的事情?我想我将不得不使用某种继承。但是,我想避免这样的事情:

MyTemplate<std::vector<int> > myTemplate;
// myTemplate.addFunc(Func1); // does not work
myTemplate.addFunc(Func2);
MyVectorTemplate<std::vector<int> > myVectorTemplate;
myVectorTemplate.addFunc(Func1);   // works  
myVectorTemplate.addFunc(Func2);

即功能应该只由传递给模板的类型决定,而不是通过选择适当的子类来确定。无论如何,我不得不承认,在这种情况下,我对如何继承有点困惑。如果它不是模板,我可以写类似的东西

class MyVectorClass : public MySingleObjectClass {}

但是,以下内容没有任何意义:

template <typename T> MyTemplate<std::vector<T> > : public MyTemplate<std::vector<T> >

但从某种意义上说,这就是我想要的。

我很抱歉这么长的帖子,我希望或多或少清楚我的问题是什么......

编辑:我刚刚在上面的代码中发现了一个错误。矢量模板中的循环应为

for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
    for (int size_t j=0;j<value.size();j++){
        mySingleElemetnFuncs[i](value[j]);
    }
}

即,每个注册函数应针对向量中的每个条目调用一次。(否则,如果注册函数的数量不等于向量的大小,则模板不起作用。

事实上,您希望向专业化添加功能,例如:

template <typename T> class MyTemplate<std::vector<T> >
{
public:
   typedef void(*MySingleElementFunc)(T);
   typedef void(*MyVectorFunc)(std::vector<T>);
   void addSingleElementFunc(MyVectorFuncf){
       this->myVcetorFuncs.push_back(f);
   }
   void addSingleElementFunc(MySingleElementFunc f){
       this->mySingleElementFuncs.push_back(f);
   }
   void callFuncs(const std::vector<T>& value){
       for (std::size_t i=0;i<myVectorFuncs.size();i++){
           myVectorFuncs[i](value);
       }
       for (std::size_t i=0;i<mySingleElementFuncs.size();i++){
           for (int size_t i=0;i<value.size();i++){
                mySingleElemetnFuncs[i](value[i]);
           }
       }
   }       
   private:
       std::vector<MySingleElementFunc> mySingleElementFuncs;
       std::vector<MyVectorFunc> myVectorFuncs;
};
template <typename T> 
class MyTemplateBase {
  // generic stuff goes here
};
template <typename T> 
class MyTemplate : public MyTemplateBase<T> {
  // nothing goes here
};
template <typename T> 
class MyTemplate<std::vector<T>> : public MyTemplateBase <std::vector<T>> {
  // specialized stuff goes here
}

如果你不想要公共继承,你可以使用私有继承,但你必须显式导出私有继承的所有内容:

template <typename T> 
class MyTemplate<std::vector<T>> : private MyTemplateBase <std::vector<T>> {
 public:
  // generic stuff re-exported
  using MyTemplateBase<std::vector<T>>::Func1;
  using MyTemplateBase<std::vector<T>>::Func2;
  // specialized stuff goes here
}

可能仍然值得,因为公共继承并不是最适合代码重用的工具。

我认为,由于 Vector 是一个模板而不是一个类,应该是这样的:

template<template <typename ...> class T /*= std::vector*/>
class SomeClass
{
    T x;
};