我知道可以使用预处理器宏来创建一个接受" stream-like"输入。为了澄清我的意思" stream-like"输入,让我举个例子( 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);
}
输出:
Foo:Bar!: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和提升解决方案。
答案 0 :(得分:2)
使用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 );
}