my_swap() 模板实例的具体情况。假设一个程序包含下面的代码:
当编译器遇到 my_swap() 调用时,它会生成一个基于调用参数的函数模板实例。模板类型的迭代器是 iterator<std::string>。在 my_swap() 模板的主体中,编译器不得不处理 tmp 的定义,编译器知道模板的类型参数是 iterator<std::string>,因此在向模板添加了这个类型后,tmp 的定义变为:
tmp 的类型现在是一个 iterator_traits 模板实例的成员变量。为了弄清楚这意味着什么,编译器需要使用 my_swap() 函数中用来指定 tmp 类型的类型参数来实例化 iterator_traits 模板。下面是一个编译器将会生成的 iterator_traits 模板实例:
从这里编译器可以确定 tmp 的类型为 iterator_traits<iterator<std::string>>::value_type,然而它也是 iterator<std::string>::value_type 的别名。就像所有的 STL 迭代器类型,iterator<std::string> 类型的定义是从 iterator 模板中生成的,并且会包含 value_type 的定义, 看起来像下面这样:
现在编译器从 iterator_traits 实例中知道 itemtor_traits<itemtor<std::string>>::value_type 是 iterator<std::string>::value_type 的别名,并且从 itemtor<std::string> 类定义中知道 iterator<std::string>:: value_type 是 std::string 的别名。通过将别名转换为真实类型,编译器推断出 my_swap() 函数中 tmp 的定义是:
有必要提醒自己模板不是代码一它是编译器用来生成代码的配方。iterator_traits 模板只包含类型别名,因此不会产生可执行代码。编译器在生成 C++ 代码的过程中,会用到它。被编译的代码中将不会有 iterator_traits 模板的踪迹;它的唯一用武之地是在生成 C++ 代码的过程中。
这里仍然遗留了一些有关指针的问题。iterator_traits 如何让算法像接受迭代器一样接受指针。iterator_traits 模板特化了类型 T* 和 const T* 的定义。例如,当模板类型参数是指针类型 T* 时,特化被定义为:
当模板类型参数是指针类型时,这定义了对应于别名的类型。T* 类型的指针 value_type 的别名总是为 T;如果将 Box* 类型的指针作为 my_swap() 的参数,那么 value_type 的别名是 Box,因此 tmp 也为这种类型。
随机访问迭代器类别所要求的全部操作都可以运用到指针上。因此对于指针,iterator_categor 的别名总是等同于 std::random_access_iterator_tag 类型。因而 iterators_traits 能否正常工作取决于模板类型参数是指针还是迭代器类类型。当模板类型参数是指针时,会选择使用 iterators_traits 针对指针的特例化模板;否则选择标准的模板定义。
如果您发现该资源为电子书等存在侵权的资源或对该资源描述不正确等,可点击“私信”按钮向作者进行反馈;如作者无回复可进行平台仲裁,我们会在第一时间进行处理!
加入交流群
请使用微信扫一扫!