透明地将 C++ 可变调用参数传递给 ostream 输出运算符
Transparent passing C++ variadic call parameters to ostream output operator
我自己编写了以下函数:
template <class Stream>
inline Stream& Print(Stream& in) { return in;}
template <class Stream, class Arg1, class... Args>
inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args)
{
sout << arg1;
return Print(sout, args...);
}
替换如下代码应该很有用:
cout << "This took " << ns << " seconds with " << np << " packets.\n";
和
Print(cout, "This took ", ns, " seconds with ", np, " packets.\n");
一切正常,除了这个函数不能“容忍”一些操纵器。好笑的,只是其中的一部分。例如,如果将 " packets.\n"
替换为 " packets.", endl
,它将不再编译。尽管 hex
或 setw(20)
都可以。问题出在哪里?
我无法解释确切原因,但如果我这样做,它不会抛出错误:
endl<char, char_traits<char>>
我的猜测是它似乎无法进行模板类型参数推断。
ostream 是:
using ostream = basic_ostream<char, char_traits<char>>;
std::endl
是函数模板。
所以不能推导重载函数
static_cast<std::ostream& (*)(std::ostream&)>(&std::endl)
会 select 纠正过载。
using Manipulator = std::ostream& (*)(std::ostream&);
Print(std::cout, "This took ", ns, " seconds with ", np, " packets.", Manipulator(std::endl));
从 C++14 开始,您甚至可以不用 helper 对流类型进行硬编码:
template <typename T>
struct ManipulatorImpl
{
ManipulatorImpl(T t) : t(t) {}
T t;
};
template <typename T>
std::ostream& operator << (std::ostream& os, ManipulatorImpl<T> m)
{
return m.t(os);
}
template <typename T>
ManipulatorImpl<T> make_ManipulatorImpl(T t) { return {t}; }
#define Manipulator(name) make_ManipulatorImpl([](auto& os) -> decltype((name)(os)) { return (name)(os); })
我自己编写了以下函数:
template <class Stream>
inline Stream& Print(Stream& in) { return in;}
template <class Stream, class Arg1, class... Args>
inline Stream& Print(Stream& sout, Arg1&& arg1, Args&&... args)
{
sout << arg1;
return Print(sout, args...);
}
替换如下代码应该很有用:
cout << "This took " << ns << " seconds with " << np << " packets.\n";
和
Print(cout, "This took ", ns, " seconds with ", np, " packets.\n");
一切正常,除了这个函数不能“容忍”一些操纵器。好笑的,只是其中的一部分。例如,如果将 " packets.\n"
替换为 " packets.", endl
,它将不再编译。尽管 hex
或 setw(20)
都可以。问题出在哪里?
我无法解释确切原因,但如果我这样做,它不会抛出错误:
endl<char, char_traits<char>>
我的猜测是它似乎无法进行模板类型参数推断。
ostream 是:
using ostream = basic_ostream<char, char_traits<char>>;
std::endl
是函数模板。
所以不能推导重载函数
static_cast<std::ostream& (*)(std::ostream&)>(&std::endl)
会 select 纠正过载。
using Manipulator = std::ostream& (*)(std::ostream&);
Print(std::cout, "This took ", ns, " seconds with ", np, " packets.", Manipulator(std::endl));
从 C++14 开始,您甚至可以不用 helper 对流类型进行硬编码:
template <typename T>
struct ManipulatorImpl
{
ManipulatorImpl(T t) : t(t) {}
T t;
};
template <typename T>
std::ostream& operator << (std::ostream& os, ManipulatorImpl<T> m)
{
return m.t(os);
}
template <typename T>
ManipulatorImpl<T> make_ManipulatorImpl(T t) { return {t}; }
#define Manipulator(name) make_ManipulatorImpl([](auto& os) -> decltype((name)(os)) { return (name)(os); })