我知道可以使用预处理器宏来创建接受"类似流"输入的函数。为了澄清我所说的"类似流"的输入是什么意思,让我举个例子(LOGGER 的输入是"类似流的"):
#include <iostream>
#include <sstream>
#define LOGGER(streamText) {
std::ostringstream buffer;
buffer << streamText;
/* Some processing */
std::cout << buffer.str() << std::endl;
}
int main(){
LOGGER("Foo: " << "Bar!: " << 42);
}
这输出:
福: 酒吧!: 42
我想为普通的C++函数提供一个类似的界面。有点像这样(不编译,C++代码无效):
// has:
// - insert( std::ostringstream & str ) function for obtaining content of a std::ostringstream
// - formatting functions
// - print( std::ostream & str ) function
class logger_class;
logger_class logger_function( some_magic_type varName ){
std::ostringstream & str = varName;
logger_class log;
log.insert( str );
return log;
}
int main(){
logger_class log = logger_function("Foo: " << "Bar!: " << 42);
log.format( some_formatting_options );
log.print( std::cout );
}
这将允许在实际发送到 std::cout 之前格式化输出。
编辑:也允许C++11和提升解决方案。
使用 C++11,您可以使用可变参数模板:
template <typename T>
std::ostringstream & fill_stream(std::ostringstream & str, T&& t)
{
return (str << std::forward<T>(t));
}
template <typename T, typename... Vs>
std::ostringstream & fill_stream(std::ostringstream & str, T&& t, Vs&&... vs)
{
str << std::forward<T>(t);
return fill_stream(std::forward<Vs>(vs)...);
}
template <typename... Ts>
logger_class logger_function( Ts&&... vars ){
std::ostringstream & str;
if (!fill_stream(str, std::forward<Ts>(vars)...))
{
//Error!
}
logger_class log;
log.insert( str );
return log;
}
然后:
int main()
{
logger_class log = logger_function("Foo: ", "Bar!: ", 42);
log.format( some_formatting_options );
log.print( std::cout );
}
如果要避免立即创建字符串流,可以创建一个将其参数存储在元组中的模板化类。
template <typename... Ts>
logger_class<Ts&&...> logger_function( Ts&&... vars ){
// logger_class should probably store its arguments as a tuple
logger_class<Ts&&...> log ( std::forward<Ts>(vars)... );
return log;
}
int main()
{
auto log = logger_function("Foo: ", "Bar!: ", 42);
log.format( some_formatting_options );
log.print( std::cout );
}