将任何对象作为一对写入文件的功能

时间:2016-11-01 20:30:56

标签: c++ ofstream

我试图编写一个模板函数,它应该将对象(不同类型的对)写入文件。就像这样:

for (auto iter = container.begin(); iter != container.end(); ++iter) {
    for (auto iter2 = std::vector<type>::reverse_iterator(iter); iter2 != container.rend(); ++iter2) {
        // do stuff
    }
}

问题是,我刚刚意识到,我需要在调用此函数时传递template<class A, class B> void write_parameters(const std::string &file_name, std::initializer_list<std::pair<A, B>> parameters) { std::ofstream file; if (!file_exists(file_name)) { file.open(file_name, std::ios_base::app); } else { file.open(file_name); } if (!file) { throw std::runtime_error("file failed to be created"); } for (std::pair<A, B> p : parameters) { file << std::string(p.first) << " = " << std::string(p.second) << "\n"; } file << "---------------------------------------------\n"; file.close(); } A的类型,因此我无法使用多个不同的地图调用此函数,或者可以我?

以下是我试图打电话的内容:

B

但这不起作用,因为例如write_parameters<std::string, std::string>(std::string("parameters/") + s.instance_name, { {"starting_node", std::string(starting_node}, {"max_iter", max_iter}, {"nice_gain", nice_gain}, {"lazy", lazy}, {"random_start", random_start} }); 不是字符串。如何解决此问题而无需为每张地图调用max_iter

1 个答案:

答案 0 :(得分:1)

传递并捕获一对对应于您想要写入的参数的对。然后你使用这个很酷的技巧来调用包中每个参数的可调用:

namespace detail{
template<class F,class...Ps>
void invoke( F&& f, Ps&&... ps ) {
    using pack=int[];
    (void)pack{((f(move(ps)),0))...};
}
}

现在变为:

template<class...Ps>
void write_parameters( std::string const& file_name, Ps&&... ps) {
  std::ofstream file(file_name,ios_base::app|ios_base::out);

  if (!file) {
    throw std::runtime_error("file failed to be created");
  }

  detail::invoke(
    [&](auto&& p) { file << p.first << " " << p.second << '\n'; },
    forward<Ps>(ps)...
  );
}

int main() {
  write_parameters(
    "parameters/" + s.instance_name,
    make_pair("starting_node", starting_node),
    make_pair("max_iter",      max_iter),
    make_pair("nice_gain",     nice_gai),
    make_pair("lazy",          lazy),
    make_pair("random_start",  random_start)
  );
}