简体   繁体   English

如何为 std::cout 制作可变参数宏?

[英]How to make a variadic macro for std::cout?

How would I make a macro that took a variable amount of arguments, and prints its out using std::cout?我如何制作一个带有可变数量参数的宏,并使用 std::cout 打印出来? Sorry if this is a noob question, couldn't find anything that clarified variadic macros after searching around for the answer.对不起,如果这是一个菜鸟问题,在搜索答案后找不到任何澄清可变参数宏的内容。

Conceptual Example:概念示例:

#include <iostream>
#define LOG(...) std::cout << ... << ... << std::endl
int main() {
    LOG("example","output","filler","text");
    return 0;
}

would output:会输出:

exampleoutputfillertext

You do not need preprocessor macros to do this.您不需要预处理器宏来执行此操作。 You can write it in ordinary C++.你可以用普通的 C++ 编写它。 In C++11/14:在 C++11/14 中:

#include <iostream>
#include <utility>

void log(){}

template<typename First, typename ...Rest>
void log(First && first, Rest && ...rest)
{
    std::cout << std::forward<First>(first);
    log(std::forward<Rest>(rest)...);
}

int main()
{
    log("Hello", "brave","new","world!\n");
    log("1", 2,std::string("3"),4.0,'\n');
}

Live demo现场演示

In C++17:在 C++17 中:

template<typename ...Args>
void log(Args && ...args)
{
    (std::cout << ... << args);
}

is all it takes.这就是全部。 Live demo现场演示

Output:输出:

Hellobravenewworld!
1234

Research variadic templates , parameter packs and fold expressions rather than variadic macros, which are rarely useful in modern C++.研究可变参数模板参数包折叠表达式,而不是可变参数宏,这在现代 C++ 中很少有用。

When using variadic macros you need __VA_ARGS__ to expand all the arguments.使用可变参数宏时,您需要__VA_ARGS__来扩展所有参数。 The problem however is that those arguments are comma-separated.然而,问题是这些参数是用逗号分隔的。 Presumabely it just separates arguments to a function call, but since macros works with just text you can actually use __VA_ARGS__ in other contexts as well, where a comma-separated list makes sense.据推测,它只是将参数与函数调用分开,但由于宏只处理文本,您实际上也可以在其他上下文中使用__VA_ARGS__ ,其中逗号分隔列表是有意义的。

The trick you can employ is to define your own comma operator for std::ostream (the type of std::cout ).您可以使用的技巧是为std::ostreamstd::cout的类型)定义自己的逗号运算符 For example:例如:

#include<iostream>
#define LOG(...) std::cout , __VA_ARGS__ , std::endl

template <typename T>
std::ostream& operator,(std::ostream& out, const T& t) {
  out << t;
  return out;
}

//overloaded version to handle all those special std::endl and others...
std::ostream& operator,(std::ostream& out, std::ostream&(*f)(std::ostream&)) {
  out << f;
  return out;
}

int main() {
  LOG("example","output","filler","text");
  return 0;
}

Now, the LOG invocation will expand to:现在,LOG 调用将扩展为:

std::cout , "example" , "output" , "filler" , "text" , std::endl;

and the commas will invoke the overloaded comma operators.并且逗号将调用重载的逗号运算符。

If you don't like overloaded operator, polluting all std::ostream -s, you can encapsulate std::cout with your own special logger class.如果你不喜欢重载operator,污染所有std::ostream -s,你可以用你自己的特殊记录器类封装std::cout

Not sure there is any way of defining a variadic macro in C++ (at least, not a portable way).不确定是否有任何方法可以在 C++ 中定义可变参数宏(至少,不是可移植的方式)。 Why don't you use a variadic template approach?为什么不使用可变参数模板方法? Something like就像是

#include <iostream>

void LOG() {}

template<typename Head, typename... Args>
void LOG(const Head& head, const Args&... args )
{
    std::cout << head << " ";
    LOG(args...);
}

int main()
{
    LOG("This", "is" , "the", 3, "rd test");
}

You can try this one你可以试试这个

#include <iostream>

#define LOG() std::cout

int main()
{
    LOG() << "Hello! " << "how " << "are " << "you " << std::endl;
    return 0;
}

Output:输出:

Hello!  how are  you 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM