有没有一种方法可以在C++中创建一个可以像Python一样使用的函数或宏?我的意思是像这样的函数
print(i); // i is an integer.
print(i, s); // i is an integer, s is a std::string. They are separated by a white space.
一个函数,它接收许多参数,然后只打印出它们,而不考虑它们的类型。
如果允许使用C++17,可以使用fold表达式,如下所示:
#include <iostream>
template<class ...Args>
void print(const Args &...args) {
auto seq_started = false;
auto print_impl = [&](auto &value) mutable {
if (seq_started) {
std::cout << " " << value;
} else {
seq_started = true;
std::cout << value;
}
};
(print_impl(args), ...);
}
int main() {
print("foo", 10, "bar", 20, "baz");
return 0;
}
使用流:
std::cout << i << ' ' << s << 'n';
对于更复杂的格式,请考虑fmt,它支持python的str.format
和printf
样式格式的语法(但类型安全(。
我假设这个问题是关于一般解决方案的,print
只是一个例子。
答案是:是的,使用重载和模板的组合。首先按类型设置功能:
void print_impl(const std::string& arg) {
std::cout << arg;
}
void print_impl(int arg) {
// Note: this is an example. Of course cout already
// does that for us with simple
// std::cout << arg;
print_impl(convert_to_string(arg));
}
// cout already has lots of overloads, we can take
// advantage of that if needed:
template<class TArg>
void print_impl(TArg&& arg) {
std::cout << std::forward<TArg>(arg);
}
然后模板:
template<class TArg>
void print(TArg&& arg) {
print_impl(std::forward<TArg>(arg));
}
template<class TArg1, class ... TArgs>
void print(TArg1&& arg1, TArgs&& ... args) {
print_impl(std::forward<TArg1>(arg1)); // <-- print first argument
print_impl(" "); // <-- insert separator, requires const std::string& overload
print(std::forward<TArgs>(args)...); // <-- recursive call
}
在上面的代码中,如果需要,您可以将对print_impl
的调用替换为直接对std::cout <<
操作员的调用。虽然我会保留print_impl
,因为它是std::cout
之上的一个很好的层,以防将来你想替换它。
然后可以使用类似于Python:的方法
int main()
{
print("test");
print(1, 2, "foo");
print("foo", 1, 2);
return 0;
}