为什么要在 C++ 标准容器中为模板参数起别名?
Why alias a template parameter in C++ standard containers?
查看Microsoft的STL代码(具体std::vector
),我遇到了以下代码行(无关代码替换为/* ... */
):
// CLASS TEMPLATE vector
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector // varying size array of values
{
/* ... */
public:
/* ... */
using value_type = _Ty;
using allocator_type = _Alloc;
using pointer = typename _Alty_traits::pointer;
using const_pointer = typename _Alty_traits::const_pointer;
using reference = _Ty&;
using const_reference = const _Ty&;
using size_type = typename _Alty_traits::size_type;
using difference_type = typename _Alty_traits::difference_type;
/* ... */
};
我想知道为什么这里使用为模板类型分配类型别名的约定?
该约定实际上用于提供“特征”。这些类型的命名遵循一些约定,允许根据这些特征编写 distance
等函数,并使其适用于许多容器。
而且我很确定标准 C++ 库的这些类型是规范的一部分,他们必须遵守它。
I was wondering why the convention of assigning a type alias to a
template type is used here?
因为是
- 标准的做法,
- 使代码不易出错,
- 减少打字,
- 更具可读性,并且
- 以上所有让生活变得轻松!
例如,让我们考虑 const_pointer
, public template alias of std::vector
using const_pointer = typename _Alty_traits::const_pointer;
在某些时候,您想知道这种类型并在函数中使用,没有上述别名怎么可能?
当然,你can write
#include <memory> // std::allocator_traits
using const_pointer = typename std::allocator_traits<typename std::vector</*type*/>::allocator_type>::const_pointer;
程序中的任何位置。但这往往 更容易出错 的情况(例如丢失一些 typename
等等),并且 更多的输入 .
因此,收集这些类型的容器并提供 public-aliases-types 是有意义的。
I was wondering why the convention of assigning a type alias to a template type is used here?
假设您有一个接受 STL 容器的模板函数(std::vector
、std::deque
、std::set
、std::multi_set
、...)
template <typename T>
void foo (T const & t)
{
// ...
}
并且您需要包含值的类型。
您可以在 foo()
中简单地写
using needed_type = typename T::value_type;
这适用于 std::vector
、std::deque
、std::set
、std::multi_set
、std::array
、std::map
、std::multi_map
等
C++ 标准要求 std::vector
提供大量嵌套名称,而这些正是问题要问的。这就是 value_type
、allocator_type
、pointer
等存在的原因。当您需要它们引用的类型时,您可以在代码中使用这些名称。例如,在用户代码中 std::vector<int>::iterator
引用 std::vector<int>
提供的迭代器类型并不罕见。
至于为什么它们是这样写的,这是一个更广泛的一致性问题。 C++ 标准库(Microsoft 提供的)的整个 Dinkumware 实现中的模板使用 _Ty
作为一般类型的基本名称。如果有两种类型,您会看到 _Ty1
和 _Ty2
。当名称有内部类型定义时,它将是 _Myty
(对于“我的”类型)。这种一致性使维护代码变得更加容易。
查看Microsoft的STL代码(具体std::vector
),我遇到了以下代码行(无关代码替换为/* ... */
):
// CLASS TEMPLATE vector
template <class _Ty, class _Alloc = allocator<_Ty>>
class vector // varying size array of values
{
/* ... */
public:
/* ... */
using value_type = _Ty;
using allocator_type = _Alloc;
using pointer = typename _Alty_traits::pointer;
using const_pointer = typename _Alty_traits::const_pointer;
using reference = _Ty&;
using const_reference = const _Ty&;
using size_type = typename _Alty_traits::size_type;
using difference_type = typename _Alty_traits::difference_type;
/* ... */
};
我想知道为什么这里使用为模板类型分配类型别名的约定?
该约定实际上用于提供“特征”。这些类型的命名遵循一些约定,允许根据这些特征编写 distance
等函数,并使其适用于许多容器。
而且我很确定标准 C++ 库的这些类型是规范的一部分,他们必须遵守它。
I was wondering why the convention of assigning a type alias to a template type is used here?
因为是
- 标准的做法,
- 使代码不易出错,
- 减少打字,
- 更具可读性,并且
- 以上所有让生活变得轻松!
例如,让我们考虑 const_pointer
, public template alias of std::vector
using const_pointer = typename _Alty_traits::const_pointer;
在某些时候,您想知道这种类型并在函数中使用,没有上述别名怎么可能?
当然,你can write
#include <memory> // std::allocator_traits
using const_pointer = typename std::allocator_traits<typename std::vector</*type*/>::allocator_type>::const_pointer;
程序中的任何位置。但这往往 更容易出错 的情况(例如丢失一些 typename
等等),并且 更多的输入 .
因此,收集这些类型的容器并提供 public-aliases-types 是有意义的。
I was wondering why the convention of assigning a type alias to a template type is used here?
假设您有一个接受 STL 容器的模板函数(std::vector
、std::deque
、std::set
、std::multi_set
、...)
template <typename T>
void foo (T const & t)
{
// ...
}
并且您需要包含值的类型。
您可以在 foo()
中简单地写
using needed_type = typename T::value_type;
这适用于 std::vector
、std::deque
、std::set
、std::multi_set
、std::array
、std::map
、std::multi_map
等
C++ 标准要求 std::vector
提供大量嵌套名称,而这些正是问题要问的。这就是 value_type
、allocator_type
、pointer
等存在的原因。当您需要它们引用的类型时,您可以在代码中使用这些名称。例如,在用户代码中 std::vector<int>::iterator
引用 std::vector<int>
提供的迭代器类型并不罕见。
至于为什么它们是这样写的,这是一个更广泛的一致性问题。 C++ 标准库(Microsoft 提供的)的整个 Dinkumware 实现中的模板使用 _Ty
作为一般类型的基本名称。如果有两种类型,您会看到 _Ty1
和 _Ty2
。当名称有内部类型定义时,它将是 _Myty
(对于“我的”类型)。这种一致性使维护代码变得更加容易。