如何使用任何类型的模板对象

时间:2013-08-07 12:37:11

标签: c++

下面的代码更改为使用智能指针:

我有一个模板类:

class IRequest;
template<class T>
class Request : public IRequest
{
public:
   Request(T in) : m_data(in) {}
   virtual ~Request() {}
   T get() { return m_data; }
   void set(T in) { m_data = in; }
private:
   T m_data;
}

在另一个课程中我有方法:

template<T>
void invoke(Request<T>& request)
{
   // Do some stuff
}
std::unique_ptr<IRequest> getRequest(int which)
{
   switch(which)
   {
   case 1:  return std::unique_ptr<IRequest>(new Request<int>(1));
   case 2:  return std::unique_ptr<IRequest>(new Request<bool>(true));
   case 3:  return std::unique_ptr<IRequest>(new Request<double>(2.0));
   default: throw std::exception();
   }
}
void run()
{
   int type = getRequestType();
   std::unique_ptr<IRequest> request = getRequest(type);
   invoke(*request);
}

问题是这样,run()方法不能模板化,必须只有1个或者它们, 并且它需要能够处理它接收的任何类型的请求,如getRequestType() 正在读取文件中的值,该文件可以包含任何类型。

编译器不喜欢这样,它希望Request在斜角括号中有一个类型, run()方法和invoke()调用。它还期望返回类型 getRequest()具有斜角括号。

是否有用于保存和传递任何类型的模板对象的C ++机制?

使用智能指针时,调用应保持原样,或者应该更改为:

void invoke<IRequest& request)

3 个答案:

答案 0 :(得分:3)

简短的回答是否定的。 Request<int>Request<double>是不同类型,Request本身不是类型。您的getRequest方法无效,因为您在不同情况下返回不同的类型。

解决此问题的一种方法是拥有Request继承的基类,例如IRequest。然后,您可以在getRequest方法中返回一个(智能)指针到IRequest

请注意,您将无法调用模板化类中的当前方法,因为您无法在基类中将它们指定为虚函数。但是,您可以将调用方法作为纯虚函数移动到基类,允许它在模板化类中实现。

class IRequest
{
public:
  virtual ~IRequest() { }
  virtual void invoke() = 0;
};


template <typename T>
class Request : public IRequest
{
public:
  Request(T in) : m_data(in) { }
  virtual ~Request() { }
  virtual void invoke() { /* Do stuff */ }

private:
  T m_data;
};

答案 1 :(得分:2)

您可以使用Boost Variant。它不仅可以声明可以返回的单一类型的请求,还可以声明一组特定的有限请求。或者您可能决定让您的请求在内部包含变量,而不是自己的模板类型。

或者,您可以使Request具有虚拟基础并实现Visitor Pattern

答案 2 :(得分:0)

您可以创建一个抽象类IRequest,它不是模板类,并使您的模板类扩展它。

然后您必须将方法的签名更改为:

IRequest& getRequest(int which)

类似地,将Requestrun()中的invoke()更改为IRequest&
您还必须确保动态分配对象的内存,而不是自动分配。