查找派生的模板类型

时间:2011-09-17 07:48:36

标签: c++ templates

我从非模板库

派生了一个模板类
struct CBaseList {
  virtual size_t Size() = 0;
};

template <class T>
struct CPointList : public BaseList { 
  virtual size_t Size() { return mData.size(); }
  std::vector <T> mData;
};

// Ok, now I can create various instances
CBaseList * lst1 = new CPointList<float> ();
CBaseList * lst2 = new CPointList<double> ();

但是如何在不同实例之间复制/分配值?例如

template <class T1, class T2>
void CopyVec( const T1 & src, T2 & dst )
{
  dst.resize(src.size());
  for (size_t i = 0; i < src.size(); ++i)
   dst[i] = src[i];    
}

void CopyList( const CBaseList * src, CBaseList * dst )
{
 // How to call CopyVec ?
}

如果我将CBaseList转换为任何派生类,那么我就是一个很难看的“切换”。有更好的解决方案吗?

由于 伊戈尔


thiton

感谢您的回复。我意识到任何编译器都应该看到/有类型来从模板生成代码 - 别无他法。但是如何紧凑地实现它一次,无需复制任何所需的模板功能?我正在考虑像这样的草图:

// caller
theWrapper(lst1, lst2)->mInstance().DoCopy(lst1, lst2, num);

// mInstance type
template <class T1, class T2>
struct CWrapInstance {
 void DoCopy( CBaseList * lst1, CBaseList * lst2, size_t num ) 
 {
  // cast types and call original template
  Copy(((T1 *) lst1)->mData, ((T2 *) lst2)->mData, num); 
 }
}; 

因此,对于每个新模板,我只需要为CWrapInstance添加一个小方法。但是如何设计“theWrapper”?

感谢您的理解。 伊戈尔

2 个答案:

答案 0 :(得分:2)

在C ++中,无法在运行时传递类型。类型不是第一类对象,类型仅在编译时存在。

您可以做的是传递类型名称(例如typeid,或者您可以创建自己的枚举,并且可以向容器中添加一个返回此枚举值的虚方法)

例如,从double转换为float的机器代码明显不同于从int转换为unsigned long long的机器代码,请记住C ++程序无法在运行时创建新代码,运行时可能需要的所有机器代码必须在编译时创建。

这意味着如果你需要创建一个多态数据容器(意思是运行时多态)并且你想在实例之间提供转换/赋值,那么必须在编译时提前创建所有可能的转换组合的代码还必须选择要使用类型名称运行的代码。

是的。不幸的是,你需要一个开关或类似的东西。

交换机的一种可能替代方法是创建转换函数映射...例如

std::map< std::pair<int, int>, void (*)(CBaseList *, CBaseList *) > converters;

给定两个类型名称返回转换函数的地址,以便您可以在地图中存储您将需要的所有转换:

template<typename U, typename V>
void assign(CBaseList *u, CBaseList *v)
{
    CPointList<U>* pu = dynamic_cast< CPointList<U> >(u);
    CPointList<V>* pv = dynamic_cast< CPointList<V> >(v);
    ...
}

void init_converters()
{
    converters[std::make_pair(FLOAT_ID, DOUBLE_ID)] = &assign<float, double>;
    converters[std::make_pair(INT_ID, DOUBLE_ID)] = &assign<int, double>;
    ...
}

然后您可以在运行时使用

动态分配
converters[std::make_pair(a->id(), b->id())](a, b);

答案 1 :(得分:1)

我认为你不能避免光荣的转换,并且6502发布了一个很好的替代方案来执行它。问题是你的类型在任何方面都没有正式相关,所以你实际上需要n ^ 2个转换函数,这些函数需要从模板中实例化,这在运行时无法完成。我推荐一种不同的设计?