2

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

有一个包装模板类,大致有这个头:

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可以是任何东西——指针、整数,甚至是重对象。

后来,Wrappers 需要放到一个容器中,比如std::vector--但不管它们的具体参数类型。这给我带来了麻烦,因为容器需要同质元素。

我已经从 KennyTM尝试过这样的基类建议,但是它给了我一些方法问题,get()并且set()- 当从向量中使用时需要强制转换(?),因为如果在该答案建议的模式中使用元素看起来像基类。

4

2 回答 2

5

为此,您将需要使用某种类型的擦除。从最基本的(提供基类型,通过指向基的指针存储元素)到更高级的解决方案,如 boost::any 你可以选择(我知道你没有提到任何提升,但你总是可以看看实现) . 或者,如果有效载荷集已知且相对较小,则可以使用变体方法(类似于 boost::variant),但这可能难以实现单次使用。

于 2012-12-13T18:14:08.200 回答
3
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);
}

a 的用户WrapperBase,如果他们想设置/获取有效负载,需要知道有效负载的类型是什么。如果您不知道,您可以使用dynamic_cast<Wrapper<Payload>*>它来确定给定的是否是特定种类。WrapperBase

这没有值语义,因此您需要存储一个vector智能指针WrapperBase而不是实际实例。 std::shared_ptr或者std::unique_ptr是行为非常不同的优秀候选人。

如果存在 的有限有界集Payloads,则访问者模式可以工作。

如果您需要值语义,pImpl存储实际有效负载的模式可以使用手动operator=克隆pImpl.

可以询问“您是否持有类型T”,但通常类似于dynamic_cast.

于 2012-12-13T18:36:53.790 回答