我想包装std::cout格式,如下所示:
mycout([what type?] x, [optional args]) {
... // do some formatting on x first
std::cout << x;
}
Run Code Online (Sandbox Code Playgroud)
并且仍然能够使用表达性语法,例如
mycout("test" << i << endl << somevar, indent)
Run Code Online (Sandbox Code Playgroud)
而不是被迫像
mycout(std::stringstream("test") << i ...)
Run Code Online (Sandbox Code Playgroud)
我该如何实施?制作什么类型x?
编辑:增加了对可选参数的考虑
使用可变参数模板参数可以很容易做到这一点:
template <class T>
void print(T t)
{
std::cout << t;
}
template <class T, class... Args>
void print(T t, Args... args)
{
std::cout << t << std::endl;
print(args...);
}
int main()
{
std::cout << std::boolalpha;
print(3, 's', true, false);
}
Run Code Online (Sandbox Code Playgroud)
输出:
3
s
true
false
这个怎么样:
struct MyCout {};
extern MyCout myCout;
template <typename T>
MyCout& operator<< (MyCout &s, const T &x) {
//format x as you please
std::cout << x;
return s;
}
Run Code Online (Sandbox Code Playgroud)
并放入MyCout myCout;任何一个 .cpp 文件中。
然后你可以myCout像这样使用:
myCout << "test" << x << std::endl;
Run Code Online (Sandbox Code Playgroud)
它会调用operator<<可以进行格式化的模板。
当然,如果需要,您还可以为特定类型的特殊格式提供运算符的重载。
编辑
显然(感谢@soon),要使标准操纵器正常工作,还需要更多的重载:
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ostream &)) {
f(std::cout);
return s;
}
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios &)) {
f(std::cout);
return s;
}
MyCout& operator<< (MyCout &s, std::ostream& (*f)(std::ios_base &)) {
f(std::cout);
return s;
}
Run Code Online (Sandbox Code Playgroud)
编辑 2
我可能稍微误解了您最初的要求。这个怎么样(加上与上面相同的操纵器重载):
struct MyCout
{
std::stringstream s;
template <typename T>
MyCout& operator << (const T &x) {
s << x;
return *this;
}
~MyCout() {
somehow_format(s);
std::cout << s.str();
}
};
int main() {
double y = 1.5;
MyCout() << "test" << y;
}
Run Code Online (Sandbox Code Playgroud)