用于在C ++中存储特定模板的对象的通用容器

时间:2012-10-21 02:28:10

标签: c++ containers generic-programming

我正在尝试创建一个通用容器,它可以存储Wrapper类型的异构对象< T>其中T可以是任何用户定义的类型。我已经看过boost :: any和其他解决方案,但是我不能在没有重铸的情况下调用函数foo()(我不知道要重铸哪种类型,关于T的信息丢失了。)它回到原始类型。

如何合理地实现Generic容器/使用现有的通用容器来实现这一目标?

template <typename T>
class Wrapper{
public:
  Wrapper(const T& a):o(a){};
  Wrapper(){};
  //public methods
  void foo(){
     //do stuff
  };
private:
 T o;
};

class X{};
class Y{};

int main(){
  X x;
  Y y;

  A_GENERIC_CONTAINER generic_container;
  // A_GENERIC_CONTAINER should be able to store
  // any number of heterogeneous objects of type Wrapper<T>
  // where T can be any user defined type.

  generic_container.push_back(x);
  generic_container.push_back(y);

  auto it =  generic_container.begin();
  auto end =  generic_container.end();
  while(it != end){
    it->foo();
    ++it;
  }
}

1 个答案:

答案 0 :(得分:4)

最通用的方法是为Wrapper创建一个基类,比如BaseWrapper,并在BaseWrapper上定义纯虚函数,然后在每个Wrapper类上实现。通过专业化,每个Wrapper,Wrapper都可以拥有自己的实现。完成后,您可以使用指向基本类型的智能指针容器,并在闲暇时使用它。

有一些可能的捷径。例如,在您的示例中,我建议使用std::function。辅助函数有助于实现此目的。注意,这只有在只有一个方法被调用时才有效。我还建议让你的包装器直接定义operator(),这样你就不必使用绑定。

template<T>
std::function<void()> wrap(const T& x)
{
   return std::bind(&Wrapper<T>::foo, Wrapper<T>(x));
}

int main(){
  X x;
  Y y;

  std::vector<std::function<void()> > generic_container;
  // A_GENERIC_CONTAINER should be able to store
  // any number of heterogeneous objects of type Wrapper<T>
  // where T can be any user defined type.

  generic_container.push_back(wrap(x));
  generic_container.push_back(wrap(y));

  auto it =  generic_container.begin();
  auto end =  generic_container.end();
  while(it != end){
    (*it)();
    ++it;
  }
}

编辑:

我所讨论的是一个非模板化的基础,你从中衍生出所有模板化的包装器。这允许您调用已预定义的方法(并且必须由Wrapper实现),而不需要知道所涉及的特定包装类型。

class Base
{
  public:
   virtual ~Base() {};
   virtual void foo() = 0;
};

template <typename T>
class Wrapper : public Base{
public:
  Wrapper(const T& a):o(a){};
  Wrapper(){};
  //public methods
  virtual void foo(){
     //do stuff
  };
private:
 T o;
};

int main(){
  X x;
  Y y;

  std::vector<std::shared_ptr<Base> > generic_container;
  // A_GENERIC_CONTAINER should be able to store
  // any number of heterogeneous objects of type Wrapper<T>
  // where T can be any user defined type.

  generic_container.push_back(std::make_shared<Wrapper<X>>(x));
  generic_container.push_back(std::make_shared<Wrapper<Y>>(y));

  auto it =  generic_container.begin();
  auto end =  generic_container.end();
  while(it != end){
    it->foo();
    ++it;
  }
}