C++模板元编程:类型选择、递归与条件定义
立即解锁
发布时间: 2025-08-16 01:21:00 阅读量: 2 订阅数: 31 


C++编程语言第四版:核心概念与技术
### C++模板元编程:类型选择、递归与条件定义
#### 1. 模板元编程基础
在模板编程中,类型函数和特性(traits)是重要的工具。例如,我们可以定义一个类型别名来获取迭代器的类别:
```cpp
template<typename T>
using Iterator_category = typename std::iterator_traits<T>::iterator_category;
```
在搜索函数的示例中,我们可以使用特性来定义函数:
```cpp
template<typename Iter>
Iter search(Iter p, Iter q, Value_type<Iter> val)
{
Difference_type<Iter> m = q - p;
// ...
}
```
然而,特性可能存在过度使用的问题。我们可以不使用特性或其他类型函数来重写上述示例:
```cpp
template<typename Iter, typename Val>
Iter search(Iter p, Iter q, Val val)
{
auto x = *p;
// if we don’t need to name *p’s type
auto m = q - p;
// if we don’t need to name q-p’s type
using value_type = decltype(*p);
// if we want to name *p’s type
using difference_type = decltype(q - p);
// if we want to name q-p’s type
// ...
}
```
这里使用了`auto`和`decltype`,它们是C++11引入的新特性。特性对于将一个类型与另一个类型关联起来是必不可少的,但如果只是为已经有合适名称的东西提供一个新名称,可能会导致混淆,因此不应盲目定义特性。
#### 2. 编译时控制结构
为了在编译时进行通用计算,我们需要选择和递归。
##### 2.1 选择
在编译时选择类型,我们可以使用`Conditional`和`Select`。
- **Conditional**:用于在两个类型之间进行选择,是`std::conditional`的别名。
```cpp
template<bool C, typename T, typename F>
// general template
struct conditional {
using type = T;
};
template<typename T, typename F>
// specialization for false
struct conditional<false, T, F> {
using type = F;
};
```
为了简化语法,我们可以引入一个类型别名:
```cpp
template<bool B, typename T, typename F>
using Conditional = typename std::conditional<B, T, F>::type;
```
例如:
```cpp
Conditional<(Is_polymorphic<T>()), X, Y> z;
```
- **Select**:用于在多个类型之间进行选择。
```cpp
class Nil {};
template<int I, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil, typename T4 = Nil>
struct select;
template<int I, typename T1 = Nil, typename T2 = Nil, typename T3 = Nil, typename T4 = Nil>
using Select = typename select<I, T1, T2, T3, T4>::type;
// Specializations for 0 - 3:
template<typename T1, typename T2, typename T3, typename T4>
struct select<0, T1, T2, T3, T4> { using type = T1; };
template<typename T1, typename T2, typename T3, typename T4>
struct select<1, T1, T2, T3, T4> { using type = T2; };
template<typename T1, typename T2, typename T3, typename T4>
struct select<2, T1, T2, T3, T4> { using type = T3; };
template<typename T1, typename T2, typename T3, typename T4>
struct select<3, T1, T2, T3, T4> { using type = T4; };
```
使用可变参数模板,我们可以提供更简单和通用的`select`:
```cpp
template<unsigned N, typename... Cases>
// general case; never instantiated
struct select;
template<unsigned N, typename T, typename ... Cases>
struct select<N, T, Cases...> : select<N - 1, Cases...> {
};
template<typename T, typename ... Cases>
// final case: N==0
struct select<0, T, Cases...> {
using type = T;
};
template<unsigned N, typename... Cases>
using Select = typename select<N, Cases...>::type;
```
##### 2.2 编译时与运行时的区别
普通的`if`语句不能用于类型选择,因为声明不能作为`if`语句分支的唯一语句。例如:
```cpp
struct Square {
constexpr int operator()(int i) { return i * i; }
};
struct Cube {
constexpr int operator()(int i) { return i * i * i; }
};
if (My_cond<T>())
using Type = Square;
// error : declaration as if-statement branch
else
using Type = Cube;
// error : declaration as if-statement branch
Type x;
// error : Type is not in scope
```
而使用`Conditional`可以正常工作:
`
0
0
复制全文
相关推荐









