我想实现这样的目标:
export_vars("path/to/file.dat", {"variable_name", obj}, {"another_variable", 2});
哪里obj
可以是任何类型,只要它有 <<
重载 - 想法是写入 ofstream
稍后的。我试过(一对 initializer_list
):
void
export_vars(const std::string& path, std::initializer_list<std::pair<std::string, std::any>> args)
{
for (auto& [name, var] : args)
std::cout << name << ": " << var << std::endl;
}
但是std::any
不能是 <<
不知道底层类型。可以使用可变参数模板和参数包扩展来实现吗?我也试过类似的东西:
template <class... Args>
void
export_vars(const std::string& path, Args... args)
{
(std::cout << ... << args.first << args.second) << std::endl;
}
但这显然是错误的。有什么建议吗?
最佳答案
{..}
没有类型,因此不允许大多数推导。
几个解决方法:
显式更改调用以使用
std::pair
:template <typename ... Pairs> void export_vars(const std::string&, const Pairs&... args) { ((std::cout << args.first << ": " << args.second << std::endl), ...); } int main() { export_vars("unused", std::pair{"int", 42}, std::pair{"cstring", "toto"}); }
不要使用模板:
void export_vars(const std::string&, const std::initializer_list<std::pair<std::string, Streamable>>& args) { for (const auto& [name, value] : args) { std::cout << name << ": " << value << std::endl; } } int main() { export_vars("unused", {{"int", 42}, {"cstring", "toto"}}); }
Streamable
使用类型删除,可能是这样的:class Streamable { struct IStreamable { virtual ~IStreamable() = default; virtual void print(std::ostream&) = 0; }; template <typename T> struct StreamableT : IStreamable { StreamableT(T t) : data(std::forward<T>(t)) {} virtual void print(std::ostream& os) { os << data; } T data; }; std::unique_ptr<IStreamable> ptr; public: template <typename T> // Possibly some concepts/SFINAE as requires(is_streamable<T>) Streamable(T&& t) : ptr{std::make_unique<StreamableT<std::decay_t<T>>>(t)} {} friend std::ostream& operator << (std::ostream& os, const Streamable& streamable) { streamable.ptr->print(os); return os; } };
关于c++ - C++ 中可变参数模板对的打印方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70155255/