上一篇写了c++模板的特化,包括全特化与偏特化,这一篇写一下c++的可变参数模板与模板模板参数
1. 可变参模板
C++ 的可变参数模板(Variadic Templates)是 C++11 引入的一个功能强大的特性,允许函数或类模板接受任意数量的参数。可变参数模板在编写通用代码时非常有用,因为它们允许你编写能够处理不同数量参数的模板,而不需要为每个可能的参数数量编写不同的重载函数或模板。
下面看案例demo:
#include <iostream>
// Base case for the recursive sum function
template<typename T>
T sum(T value) {
return value;
}
// Recursive sum function for variadic template
template<typename T, typename... Args>
T sum(T first, Args... rest) {
return first + sum(rest...);
}
int main() {
std::cout << sum(1, 2, 3, 4, 5) << std::endl; // Output: 15
std::cout << sum(1.1, 2.2, 3.3, 4.4, 5.5) << std::endl; // Output: 16.5
return 0;
}
上面是一个简单的示例,说明了如何使用可变参数模板编写一个函数来计算参数的总和,在这个例子中,sum
是一个接受任意数量参数的模板函数。首先定义了一个基本的模板 sum(T value)
,它接受单个参数并返回它自身。然后定义了一个递归版本的 sum
,它接受一个参数 first
和一个参数包 Args... rest
。这个函数将第一个参数 first
与剩余参数的总和相加,并递归调用 sum(rest...),
通过这种方式,无论传递多少个参数给 sum
,它都能正确地计算它们的总和。
可变参模板不仅可以用于函数,还能用于类,当使用可变参数模板来定义类模板时,你可以让类接受任意数量的模板参数,并在类内部使用这些参数。这种灵活性使得你能够创建更通用和灵活的类。
下面看案例demo:
#include <iostream>
// Base case for the recursive tuple class template
template<typename... Args>
class Tuple {};
// Recursive tuple class template to hold multiple types
template<typename T, typename... Args>
class Tuple<T, Args...> {
private:
T value;
Tuple<Args...> rest;
public:
Tuple(T value, Args... args) : value(value), rest(args...) {}
T get() const { return value; }
Tuple<Args...> getNext() const { return rest; }
};
int main() {
Tuple<int, double, std::string> myTuple(42, 3.14, "Hello");
std::cout << "First element: " << myTuple.get() << std::endl;
std::cout << "Second element: " << myTuple.getNext().get() << std::endl;
std::cout << "Third element: " << myTuple.getNext().getNext().get() << std::endl;
return 0;
}
上面这个事例演示了如何使用可变参数模板来定义一个元组(Tuple)类模板,定义了一个基础版本的 Tuple
类模板,该模板不接受任何模板参数。然后定义了一个递归版本的 Tuple
类模板,该模板接受一个模板参数 T
和一个参数包 Args...
。这个模板包含一个值成员 value
,以及一个类型为 Tuple<Args...>
的成员 rest
,它代表了剩余的参数。
在 main
函数中,我们创建了一个 Tuple
对象 myTuple
,它包含一个整数、一个双精度浮点数和一个字符串。然后,我们使用 get()
和 getNext()
方法分别访问元组的各个元素。
2. 模板模板参数
模板模板参数(Template Template Parameters)是 C++ 中一种高级的模板特性,允许你将模板作为模板参数传递给另一个模板。这种技术在编写泛型代码时非常有用,因为它可以增加代码的灵活性和通用性。使用模板模板参数,你可以定义接受模板作为参数的模板。这使得你可以在模板中指定更抽象的模板类型,而不仅仅是具体的类型。
下面是模板模板参数的简单使用:
#include <iostream>
// 定义一个模板类
template <typename T>
class Container {
public:
T element;
void print() const{
std::cout << element << std::endl;
}
};
// 使用模板模板参数定义一个模板函数
template <template <typename> class ContainerType, typename ValueType>
void printContainer(const ContainerType<ValueType>& container) {
container.print();
}
int main() {
Container<int> intContainer{42};
printContainer(intContainer); // 输出: 42
Container<double> doubleContainer{3.14};
printContainer(doubleContainer); // 输出: 3.14
return 0;
}
在这个示例中,printContainer
函数使用了模板模板参数 template <typename> class ContainerType
,它接受一个模板作为参数,并且该模板接受一个类型参数。这样一来,你就可以将 Container
类模板作为参数传递给 printContainer
函数。通过这种方式,printContainer
函数能够处理不同类型的容器,而不仅限于特定的类型。
总之,模板模板参数是一种强大的技术,它允许你编写更加通用和灵活的泛型代码,从而提高了代码的重用性和可扩展性