变参模板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);
}