尝试使用可变参数模板模仿 python 打印功能无效
Attempt at mimicking the python print function using variadic templates not working
我在看书时遇到了 可变参数模板,我认为实现一个 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
),用于指定
打印(即换行符,space,等)。
- 拆分函数
print
其中一个将用于打印一个参数
时间,我们将检查打印方式;
- 另一个
print
将用于调用 variadic
参数
由来电者。这里我们使用 fold
要调用的表达式
第一个 print
过载。
类似于:(Live Demo)
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);
“你不喜欢重载!?” 然后我们可以在立即调用 lambda 函数的帮助下将它放在单个 print
函数中。
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 风格的 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
),用于指定 打印(即换行符,space,等)。 - 拆分函数
print
其中一个将用于打印一个参数 时间,我们将检查打印方式; - 另一个
print
将用于调用 variadic 参数 由来电者。这里我们使用 fold 要调用的表达式 第一个print
过载。
类似于:(Live Demo)
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);
“你不喜欢重载!?” 然后我们可以在立即调用 lambda 函数的帮助下将它放在单个 print
函数中。
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
}