使用可变参数函数/宏简化工作

时间:2016-10-18 15:01:42

标签: c++ c++11 variadic-functions variadic-macros

我正在写一堆像这样的函数:

template <>
Error SyntaxError<unfinished_string>(unsigned int line) {
    std::stringstream message;
    message << "SyntaxError: unfinished string (starting at line " << line << ").";
    return Error(Error::Type::syntax, message.str());
}

template <>
Error SyntaxError<malformed_number>(std::string number, unsigned int line) {
    std::stringstream message;
    message << "SyntaxError: malformed number (" << number << ") at line " << line << '.';
    return Error(Error::Type::Syntax, message.str());
}

...

使用类似于以下内容的可变函数/宏也不错:

Error proto(/*variable number & type of arguments*/) {
    std::stringstream message;
    message << "SyntaxError: " << /*arguments passed, separated by <<s */;
    return Error(Error::Type::syntax, message.str());
}

这样我就可以将我的函数编写为:

template <>
Error SyntaxError<unfinished_string>(unsigned int line) {
    return proto("unfinished string (starting at line ", line, ").");
}

template <>
Error SyntaxError<malformed_number>(std::string number, unsigned int line) {
    return proto("malformed number (", number, ") at line ", line, '.');
}

这有可能吗?如果是的话?

1 个答案:

答案 0 :(得分:1)

如果要转换可变参数列表并将它们完全流式传输,那么可以实现一个附加函数,以递归方式将每个参数附加到该流。 例如:

template< typename FirstArg, typename... Args >
inline std::ostream& join_args( std::ostream& os, FirstArg arg, Args... args ) {
   os << arg;
   return join_args( os, args... );
}

一步一步,你会筋疲力尽。请务必处理您处理的订单,( std::ostream& os, FirstArg arg, Args... args )( std::ostream& os, Args... args, LastArg arg )不同。

最后但并非最不重要的,你应该涵盖角落案件(一个或没有参数,取决于你的问题):

inline std::ostream& join_args( std::ostream& os ) {
   return os;
}

不要担心递归效率,编译器将能够内联所有函数调用(因为它在编译时知道递归的深度)并将所有代码展平,以便生成的程序将是或多或少相当于手动将所有参数附加到单个流中。