我正在构建一个我想要使用各种参数配置的类,这些参数可以是:int,double和string(或者const char *).在像Ruby这样的语言中,我将构建一个初始化函数,该函数接受由字符串键入的哈希值.例如:
class Example
def init_with_params params
puts params
end
end
e = Example.new
e.init_with_params({ "OutputFile" => "/tmp/out.txt", "CaptureFPS" => 25.0, "RetryDelaySeconds" => 5 })
如何在C中创建类似的行为?
环顾四周,我发现了几篇关于boost :: variant的帖子.我宁愿避免使用boost如果通过将不同类型限制为上面提到的3种类型,可以制作一个相当干净的解决方案.
编辑:
我同意使用经过精心设计和广泛测试的代码(如Boost.Variant)比重新实现相同的想法要好得多.在这种情况下,问题减少到只使用3种基本类型,所以我一直在寻找最简单的实现方法.
解决方法:
这是我经常用来存储程序配置属性的减少版本,也许你会发现它很有用:
#include <map>
#include <string>
#include <sstream>
#include <fstream>
#include <iostream>
#include <initializer_list>
class config
{
// everything is stored internally as std::strings
// usually read from a configuration file
typedef std::map<std::string, std::string> prop_map;
typedef prop_map::const_iterator prop_map_citer;
prop_map props;
public:
// example constructor. Normally I have a method to read the
// values in from a file
config(std::initializer_list<std::pair<std::string, std::string>> list)
{
for(const auto& p: list)
props[p.first] = p.second;
}
// values are converted as they are requested to whatever types
// they need to be. Also a default may be given in case the value
// was missing from the configuration file
template<typename T>
T get(const std::string& s, const T& dflt = T()) const
{
prop_map_citer found = props.find(s);
if(found == props.end())
return dflt;
T t;
std::istringstream(found->second) >> std::boolalpha >> t;
return t;
}
// std::strings need special handling (no conversion)
std::string get(const std::string& s, const std::string& dflt = "") const
{
prop_map_citer found = props.find(s);
return found != props.end() ? found->second : dflt;
}
};
int main()
{
const config cfg =
{
{"OutputFile", "/tmp/out.txt"}
, {"CaptureFPS", "25.0"}
, {"RetryDelaySeconds", "5"}
};
std::string s;
float f;
int i;
s = cfg.get("OutputFile");
f = cfg.get<float>("CaptureFPS");
i = cfg.get<int>("RetryDelaySeconds");
std::cout << "s: " << s << '\n';
std::cout << "f: " << f << '\n';
std::cout << "i: " << i << '\n';
}