如何在STL容器中存储模板化的异构对象 [英] How to store templated heterogeneous objects in an STL container

查看:166
本文介绍了如何在STL容器中存储模板化的异构对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题是关于在MS Visual C ++ 11中开发的代码,只能访问STL,没有提升。



有一个包装模板类, header:

  template< typename Payload> 
class Wrapper {
Payload p;
std :: string src;
包装器(std :: string,Payload);

Payload get(); //返回有效载荷
void set(Payload); //替换有效载荷
void operator()(); //使用负载
}

Payload 可能是任何东西 - 指针,int,甚至重对象。



稍后, Wrapper 需要进入一个容器,像 std :: vector - 但是不管它们具体的参数类型。这给我带来麻烦,因为容器需要同质元素。



我已经尝试了基类建议像KennyTM这样的,然而它给我提供了一些方法 get() set() - 当从一个向量中使用时,需要使用cast(?),因为如果在该答案建议的模式中使用了元素,那么元素看起来像是一个基类。

  template< typename Payload> 
struct Wrapper;

struct WrapperBase {
std :: string src;
WrapperBase(std :: string s):src(s){}
模板< typename Payload>
Payload get()const;
模板< typename Payload>
void set(Payload);
virtual void operator()()= 0; //使用有效载荷
};

模板< typename Payload>
struct Wrapper {
Payload payload;
Wrapper(std :: string s,Payload p):WrapperBase(s),payload(p){}

Payload get()const {return payload; }; //返回有效载荷
void set(Payload p){payload = p; }; //替换有效载荷
virtual void operator()()override; // todo
}

模板< typename Payload>
Payload WrapperBase :: get()const {
Assert(dynamic_cast< Wrapper< Payload> const *>(this));
返回static_cast< Wrapper< Payload>常量*>(这个) - GT;获得();
}
模板< typename Payload>
void WrapperBase :: set(Payload p){
Assert(dynamic_cast< Wrapper< Payload> *>(this));
static_cast< Wrapper< Payload> *>(this) - > set(p);

WrapperBase ,如果他们想要设置/获取有效载荷,则需要知道有效载荷的类型。您可以使用 dynamic_cast< Wrapper< Payload> *> 来判断给定的 WrapperBase 是否为特定类型if你不知道。



这没有价值语义,所以你需要存储一个 vector 的智能指针指向 WrapperBase ,而不是实际的实例。 std :: shared_ptr std :: unique_ptr 是非常不同行为的好候选人。



如果有一个有限的 Payloads 有界集合,访客模式可以工作。



如果你需要价值语义,一个存储实际有效负载的 pImpl 模式可以通过 operator = 来完成。克隆 pImpl



询问你是否持有类型 T 是可能的,但通常类似于 dynamic_cast


The question is about a code developed in MS Visual C++ 11, with access only to STL, no Boost.

There is a wrapper template class, roughly with this header:

template <typename Payload>
class Wrapper {
  Payload p;
  std::string src;
  Wrapper( std::string, Payload );

  Payload get();      // returns payload
  void set(Payload);  // replaces payload
  void operator ()(); // uses payload
}

Payload may be anything - pointer, int, even heavy object.

Later, Wrappers need to go in a container, like std::vector - but regardless of their specific parameter type. And that gives me trouble because container needs homogeneous elements.

I have tried the base class suggestions like this from KennyTM, however it gives me some issues with methods get() and set() - those need cast (?) when used from a vector because elements look like a base class if used in the pattern suggested by that answer.

解决方案

template<typename Payload>
struct Wrapper;

struct WrapperBase {
  std::string src;
  WrapperBase( std::string s ):src(s) {}
  template<typename Payload>
  Payload get() const;
  template<typename Payload>
  void set(Payload);
  virtual void operator ()() = 0; // uses payload
};

template <typename Payload>
struct Wrapper {
  Payload payload;
  Wrapper( std::string s, Payload p ):WrapperBase(s),payload(p) {}

  Payload get() const { return payload; };      // returns payload
  void set(Payload p) { payload = p; };  // replaces payload
  virtual void operator()() override; // todo
}

template<typename Payload>
Payload WrapperBase::get() const {
  Assert(dynamic_cast<Wrapper<Payload> const*>(this));
  return static_cast<Wrapper<Payload> const*>(this)->get();
}
template<typename Payload>
void WrapperBase::set(Payload p) {
  Assert(dynamic_cast<Wrapper<Payload>*>(this));
  static_cast<Wrapper<Payload>*>(this)->set(p);
}

Users of a WrapperBase, if they want to set/get the payload, need to know what the type of the payload is. You can use dynamic_cast<Wrapper<Payload>*> to figure out if a given WrapperBase is a specific kind if you don't know.

This doesn't have value semantics, so you'll want to store a vector of smart pointers to WrapperBase rather than actual instances. std::shared_ptr or std::unique_ptr are good candidates with very different behavior.

If there is a finite bounded set of Payloads, a visitor pattern can work.

If you need value semantics, a pImpl pattern that stores the actual payload can do that with manual operator= that clones the pImpl.

Asking "do you hold type T" is possible, but generally is similar to a dynamic_cast.

这篇关于如何在STL容器中存储模板化的异构对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆