运行时c ++的模板参数

时间:2012-11-10 17:19:17

标签: c++ templates

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

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

我不喜欢这个if-else-循环,是否有任何方法可以避免这种情况,或者是否有其他解决此问题的方法?

2 个答案:

答案 0 :(得分: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
}

希望这有帮助。

答案 1 :(得分: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类),也可以间接创建(即,您获取variant并生成适当的Property<T> },它解析为从类型抽象中解析代码。)

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