C++ std ::模板类值的映射

jba*_*sta 13 c++ methods templates stdmap

我试图声明一个Row和一个Column类,Row有一个私有std::map值指向模板Column.像这样的东西:

template <typename T> class DataType {
  private:
    T type;
};
template <typename T> class Field {
  private:
    T value;
    DataType<T> type;
};
class Row {
  private:
    std::map<unsigned long,Field*> column;
}; 
Run Code Online (Sandbox Code Playgroud)

好吧,我原则上认为Row类不应该知道我们想要使用哪种Field(或Column),即它是第1 Field<int>列还是第Field<double>2列.但是我不确定什么是正确的语法对于Row::column声明,或者如果std::map它在这个意义上是有限的,我应该使用其他东西.

我建议你提出建议,并提前感谢你们.

Joh*_*itb 24

Field单独不是一种类型,而是一种可以生成一系列类型的模板,例如Field<int>Field<double>.所有这些字段都不相关,使得一个字段以某种方式从另一个或那样派生.所以你必须在所有这些生成的类型之间建立一些关系.一种方法是使用通用的非模板基类:

class FieldBase { };

template <typename T>
class Field : public FieldBase {
  private:
    T value;
    DataType<T> type;
};
class Row {
  private:
    std::map<unsigned long,FieldBase*> column;
}; 
Run Code Online (Sandbox Code Playgroud)

并考虑在代码中使用智能指针而不是原始指针.无论如何,现在问题是类型信息丢失了 - 无论你指向a Field<double>还是a Field<int>都不知道,只能通过在模板派生类设置的基数中保留某种type-flag来检测它. - 或者通过询问RTTI

dynamic_cast<Field<int>*>(field) != 0
Run Code Online (Sandbox Code Playgroud)

但那很难看.特别是因为你想要的是一个价值语义.也就是说,你希望能够复制你的行,它会复制其中的所有字段.并且你想要在存储双精度时得到一个双精度 - 而不是先使用RTTI来破解你的派生类型.

一种方法是使用有区别的联合.这基本上是一些任意类型的并集,另外还有一个type-flag,它存储当前存储在该字段中的值(例如,是否为double,int,...).例如:

template <typename T>
class Field {
  private:
    T value;
    DataType<T> type;
};
class Row {
  private:
    std::map<unsigned long, 
             boost::variant< Field<int>, Field<double> > > 
      column;
};
Run Code Online (Sandbox Code Playgroud)

boost :: variant为您完成所有工作.您可以使用访问来使用正确的重载来调用仿函数.看看它的手册