变参模板2:包展开
题目描述
对于一个函数形参包 args
,它更常见的使用方式是包展开。包展开最简单的做法,就是在后面加上 ...
,这样 args...
就会被替换为每一个形参的具体值用逗号分隔开来的形式。
比如下面的代码会从形参包生成包含全部形参作为元素的 std::vector
:
template <typename... Ts>
std::vector<int> f(Ts... args) {
return { args... };
}
f(1, 2, 3); // 返回包含 {1, 2, 3} 的 std::vector
任何期望“逗号分隔的值的列表”的地方都可以出现形参包的展开,比如函数调用表达式的实参列表。下面的代码可以将形参包的首个形参的值输出:
template <typename T, typename... Us>
void outputFirst(T t, Us...) {
std::cout << t << std::endl;
}
template <typename... Ts>
void f(Ts... args) {
outputFirst(args...); // 输出 args 中首个形参
}
类似地,通过适当的“递归”和重载,就可以将形参包 args
中的所有值输出。接下来,请实现 print
函数,它将任意多的形参通过 std::cout
输出。
关于输入
无
关于输出
见样例输出
参考答案
#include <iostream>
#include <string>
void print() {
std::cout << std::endl;
}
template <typename T, typename... Args>
void print(const T& t, const Args&... args) {
std::cout << t;
print(args...);
}
int main() {
std::string n("nullptr");
print(false);
print();
print("hello", " world");
print("do not ", "dereference ", n);
print(1, '+', 1LL, "=", 2.0);
}
#include <iostream>
#include <string>
template <typename T, typename... Args>
void printArgs(const T& t, const Args&... args) {
std::cout << t;
if constexpr (sizeof...(args) > 0) {
printArgs(args...);
}
}
template <typename... Args>
void print(const Args&... args) {
if constexpr (sizeof...(args) > 0) {
printArgs(args...);
}
std::cout << std::endl;
}
int main() {
std::string n("nullptr");
print(false);
print();
print("hello", " world");
print("do not ", "dereference ", n);
print(1, '+', 1LL, "=", 2.0);
}
#include <iostream>
#include <string>
template <typename... Args>
void print(const Args&... args) {
(std::cout << ... << args) << std::endl;
}
int main() {
std::string n("nullptr");
print(false);
print();
print("hello", " world");
print("do not ", "dereference ", n);
print(1, '+', 1LL, "=", 2.0);
}