关于c ++:如何为std :: cout创建可变参数宏?

How to make a variadic macro for std::cout?

我如何制作一个带有可变数量参数的宏,并使用std :: cout打印出来? 很抱歉,如果这是一个菜鸟问题,在寻找答案后找不到任何能够阐明可变参数宏的内容。

概念示例:

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

将输出:

1
exampleoutputfillertext


您不需要预处理器宏即可执行此操作。你可以用普通的方式写
C ++。在C ++ 11/14中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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!
"
);
    log("1", 2,std::string("3"),4.0,'
'
);
}

现场演示

在C ++ 17中:

1
2
3
4
5
template<typename ...Args>
void log(Args && ...args)
{
    (std::cout << ... << args);
}

就是全部。现场演示

输出:

1
2
Hellobravenewworld!
1234

研究可变参数模板,
参数包
和折叠表达式
而不是可变参数宏,在现代C ++中很少使用。


使用可变参数宏时,您需要__VA_ARGS__来扩展所有参数。
但是,问题在于这些参数是用逗号分隔的。大概是,它只是将参数分开给函数调用,但是由于宏仅与文本一起使用,因此您实际上还可以在其他上下文中使用__VA_ARGS__,在这种情况下,逗号分隔的列表很有意义。

您可以采用的技巧是为std::ostream(std::cout的类型)定义自己的逗号运算符。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#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;
}

现在,LOG调用将扩展为:

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

逗号将调用重载的逗号运算符。

如果您不喜欢过载的operator,污染所有std::ostream -s,则可以使用自己的特殊记录器类封装std::cout


不确定是否有任何方法可以在C ++中定义可变参数宏(至少不是可移植的方法)。为什么不使用可变参数模板方法?就像是

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#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");
}


你可以试试这个

1
2
3
4
5
6
7
8
9
#include <iostream>

#define LOG() std::cout

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

输出:

1
Hello!  how are  you