0

我写了一个 C++ 模板类,但我没有实例化该类的类型。类型以字符串格式存储。所以我必须做这样的事情:

if ( propType == "char") {
   Property<char> pChar = ...
} else if ( propType == "int") {
   Property<int> pChar = ...
} if ( propType == "double") {
   Property<double> pChar = ...
} 

我不喜欢这个if-else-循环,有什么方法可以避免这种情况,或者有什么其他解决方案可以解决这个问题吗?

4

2 回答 2

4

方法很多,但如果不知道在特定情况下如何使用它,就不可能选择一个好的方法。

作为演示:

  • 让我们假设所有Property<T>类都继承自PropertyBase
  • 让我们假设您通过解析字符串中的类型来初始化它们

下面是一些代码:

using PropertyPtr = std::unique_ptr<PropertyBase>;
using Parser = std::function<PropertyPtr(std::string const&, std::string const&)>;

template <typename T>
PropertyPtr parse(std::string const& type, std::string const& value) {
    T v = boost::lexical_cast<T>(value);
    return PropertyPtr(new Property<T>(std::move(v)));
}

std::map<std::string, Parser> const parsers = {
    std::make_pair("char", parse<char>),
    std::make_pair("int", parse<int>),
    std::make_pair("double", parse<double>)
};

void dummy(std::string const& type, std::string const& value) {
    auto const it = parsers.find(type);
    assert(it == parsers.end() && "No parser");

    auto const& parser = it->second;
    PropertyPtr property = parser(type, value);

    // do something with property
}

希望这可以帮助。

于 2012-11-10T17:46:47.043 回答
1

这里有几个考虑因素。

假设您要从磁盘解析文件,然后根据您要创建对象的磁盘类型。您以几乎无法区分的方式处理这些对象。您正在使用的类型是有限的。

我为此使用的答案是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>,它将解析代码与您的类型抽象解耦)。

基本上,您需要在类型擦除、类型抽象和基于模板的编程之间做出决定,以处理多种类型。他们都有自己的优势。

于 2012-11-10T18:22:46.193 回答