尝试使用可变参数模板模仿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
}


以上是尝试使用可变参数模板模仿python打印功能不起作用的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>