尝试使用可变参数模板模仿python打印功能不起作用
我在看书时遇到了可变参数模板,并认为实现一个 python 风格的print函数会很酷。
这是代码。
#include <iostream>
#include <string>
#define None " "
template<typename T, typename... Tail>
void print(T head, Tail... tail, const char* end = "n")
{
std::cout << head << end;
if constexpr (sizeof...(tail) > 0)
{
print(tail..., end);
}
}
int main()
{
// Error: no instance of function template "print" matches the argument list
print("apple", 0, 0.0f, 'c', true);
// Error: no instance of function template "print" matches the argument list
print("apple", 0, 0.0f, 'c', true, None);
}
这两个函数调用的预期结果:
First: Second:
apple apple 0 0.0f 'c' 1
0
0.0f
'c'
1
const char* end = "n"从函数签名中删除可以编译代码,但我想要指定最后一个参数来声明是否打印换行符的功能。
这可能吗?
回答
这是可能的,但不是您尝试过的方式。
您可以执行以下操作(c++17 中的一种可能解决方案):
- 提供一个枚举 (
Ending),它将用于指定打印方式(即换行、带空格等)。 - Split 函数
print,其中一个将用于一次打印一个参数,我们将检查打印方式; - 另一个
print将用于调用
者调用可变参数。这里我们使用折叠表达式 来调用第一个print重载。
喜欢的东西:(现场演示)
enum struct Ending { NewLine = 0, Space };
template<Ending end, typename Type>
void print(const Type& arg) noexcept
{
if constexpr (end == Ending::NewLine) {
std::cout << arg << 'n';
}
else if constexpr (end == Ending::Space) {
std::cout << arg << ' ';
}
}
template <Ending end, typename... Args>
void print(const Args& ... args) noexcept
{
(print<end>(args), ...);
}
现在您可以指定如何结束该行
print<Ending::NewLine>("apple", 0, 0.0f, 'c', true);
print<Ending::Space>("apple", 0, 0.0f, 'c', true);
“你不喜欢超载!?” 然后我们可以在print 立即调用 lambda 函数的帮助下将其放入单个函数中。
(现场演示)
template <Ending end, typename... Args>
void print(const Args& ... args) noexcept
{
([] (Ending, const auto& arg) noexcept {
if constexpr (end == Ending::NewLine) {
std::cout << arg << 'n';
}
else if constexpr (end == Ending::Space) {
std::cout << arg << ' ';
}
}(end, args), ...);
//^^^^^^^^^^ ^^^^ ---> Invoke the lambda & expand the fold
}