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



我知道可以使用预处理器宏来创建接受"类似流"输入的函数。为了澄清我所说的"类似流"的输入是什么意思,让我举个例子(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 );
}

相关内容

  • 没有找到相关文章

最新更新