使用“Stream-like”输入到C ++函数

时间:2014-01-15 14:17:06

标签: c++ stream stringstream

我知道可以使用预处理器宏来创建一个接受" 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和提升解决方案。

1 个答案:

答案 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 );
}