这里有几个考虑因素。
假设您要从磁盘解析文件,然后根据您要创建对象的磁盘类型。您以几乎无法区分的方式处理这些对象。您正在使用的类型是有限的。
我为此使用的答案是boost::variant
存储数据,以及map
将类型名称映射到该类型的读取器(或解析器)的(如 Matthiew 的答案)。然后阅读器返回一个boost::variant<int, double, char, string, etc>
.
然后代码以伪统一的方式与变体交互。辅助函数使用 boost 函数来调用函子与variant
.
即,像这样:
typedef boost::variant<int, double> myVariant;
typedef std::function< myVariant( input_stream_type& ) > ValueParser;
ValueParser GetParser( std::string typename );
// ...
struct DoTypeSpecificWork
{
typedef void result_type;
void operator()( int ) { /* ... int code goes here */ }
void operator()( double ) { /* ... double code goes here */ }
};
ValueParser parser = GetParser( propType );
myVariant var = parser( input_stream );
boost::variant::apply_visitor( DoTypeSpecificWork(), var );
另一种选择是拥有一个PropertyBase
具有与类型无关的抽象接口的基类。然后Property<T>
是为每种类型实现这些抽象接口的子类。创建这些Property<T>
子类可以直接完成(强制解析器了解您的Property
类),也可以间接完成(即,您获取 avariant
并生成一个适当的Property<T>
,它将解析代码与您的类型抽象解耦)。
基本上,您需要在类型擦除、类型抽象和基于模板的编程之间做出决定,以处理多种类型。他们都有自己的优势。