根据字符串参数的内容选择模板

时间:2019-07-05 16:12:21

标签: c++ boost std

我在使用boost::property_tree时遇到了一个问题,该问题可能具有更多的通用应用程序。我的目标是创建一个加载程序功能,该功能能够根据文件扩展名选择正确的加载程序。我的解决方案是使用连续的if else-if语句:

auto extension = input_filename.extension().string();
if(iequals(extension, ".json"))      pt::read_json(input_filename.string(), tree);
else if(iequals(extension, ".info")) pt::read_info(input_filename.string(), tree);
else if(iequals(extension, ".xml"))  pt::read_xml(input_filename.string(), tree);
else if(iequals(extension, ".ini"))  pt::read_ini(input_filename.string(), tree);
else   ... // unknown file type

我认为应该有一个比这更好的解决方案。如果我记得python,您可以在其中做类似map<extension, function>[extension](input_filename.string(), tree)的事情,那么它启发了我以下几点。想法是使用映射在扩展字符串和函数之间创建关系:

using loader_fct = void(*)(const std::string &, pt::ptree &, const std::locale &);
using loader_table = std::map<std::string, loader_fct>;

const loader_table load_funct{
        {".json", &pt::read_json},
        {".ini",  &pt::read_ini},
        {".info", &pt::read_info},
//      {".xml",  &pt::read_xml}
};

第一个问题是,显然并非所有的加载器函数(-templates)都具有相同的签名,因此我们不能使用xml。此外,我们必须定义所有模板参数,然后可以通过以下方式使用它:

auto extension = boost::to_lower_copy(input_filename.extension().string());
auto loader = load_funct.find(extension);
loader->second(input_filename.string(), tree, std::locale());

我能够借助一些模板来解决具有不同功能签名的问题,这使我们可以简化一些:

template<typename Ptree>
void read_json(const std::string & s, Ptree & t) { pt::read_json(s, t); }

template<typename Ptree>
void read_ini(const std::string & s, Ptree & t) { pt::read_ini(s, t); }

template<typename Ptree>
void read_info(const std::string & s, Ptree & t) { pt::read_info(s, t); }

template<typename Ptree>
void read_xml(const std::string & s, Ptree & t) { pt::read_xml(s, t); }

using loader_table = std::map<std::string, void(*)(const std::string &, pt::ptree &)>;
loader_table load_funct{
        {".json", &read_json},
        {".ini",  &read_ini},
        {".info", &read_info},
        {".xml",  &read_xml}
};
auto extension = boost::to_lower_copy(input_filename.extension().string());
if(load_funct.count(extension))
{
        load_funct[extension](input_filename.string(), tree);
}

我的基本问题:

有更好的方法吗?还是其他想法?

最后一个解决方案使我思考是否有可能选择模板中已经存在的正确加载器?

0 个答案:

没有答案