std::vector 构造函数采用一对迭代器
std::vector constructor taking pair of iterators
我正在制作某种容器,我想模仿 std::vector
. However, I am having a hard time understanding how the constructor overload (4) 作品的界面。问题是它通常与重载(2)冲突。
// (2)
vector(size_type count, const T& value, const Allocator& alloc = Allocator());
// (4)
template<class InputIt>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
根据 cppreference,C++11 之前:
this constructor has the same effect as overload (2) if InputIt is an integral type.
我了解它是如何完成的(我想是标签分派或模板特化),但我不知道 C++11 中的新行为是如何实现的:
This overload only participates in overload resolution if InputIt satisfies InputIterator, to avoid ambiguity with the overload (2).
这是某种 SFINAE 把戏吗?我不明白 SFINAE 怎么能在这里工作。而且,由于 C++11(也不是 C++14)中的概念与否,我不知道如何为我的容器做到这一点。
因此我的问题是:它是如何在标准库中完成的(或者至少是一个猜测),我如何才能相对轻松地为我的容器完成它?
标准中目前的措辞方式相当有趣。 [sequence.reqmts]/p15:
The extent to which an implementation determines that a type cannot be
an input iterator is unspecified, except that as a minimum integral
types shall not qualify as input iterators.
换句话说,实现只测试整数类型就足够了,但如果他们愿意,他们可以做更多。
使用 SFINAE 友好的 std::iterator_traits
(作为 LWG 问题投票进入 C++17 工作文件,但可能一直由大多数实现提供),例如,可以测试 std::iterator_traits<InputIterator>::iterator_category
是有效的,表示从 std::input_iterator_tag
派生的类型,类似于
template<class InputIt, std::enable_if_t<std::is_base_of<std::input_iterator_tag,
typename std::iterator_traits<InputIterator>::iterator_category>::value, int> = 0>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
请注意,这只是概念验证。标准库中的实际实现可能 1) 更复杂(例如,它可能基于迭代器类别进行优化 - 对于前向迭代器或更好的迭代器,它可以一次性为所有元素分配内存)和 2) 甚至比这更丑陋和填充下划线以避免名称冲突。
我正在制作某种容器,我想模仿 std::vector
. However, I am having a hard time understanding how the constructor overload (4) 作品的界面。问题是它通常与重载(2)冲突。
// (2)
vector(size_type count, const T& value, const Allocator& alloc = Allocator());
// (4)
template<class InputIt>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
根据 cppreference,C++11 之前:
this constructor has the same effect as overload (2) if InputIt is an integral type.
我了解它是如何完成的(我想是标签分派或模板特化),但我不知道 C++11 中的新行为是如何实现的:
This overload only participates in overload resolution if InputIt satisfies InputIterator, to avoid ambiguity with the overload (2).
这是某种 SFINAE 把戏吗?我不明白 SFINAE 怎么能在这里工作。而且,由于 C++11(也不是 C++14)中的概念与否,我不知道如何为我的容器做到这一点。
因此我的问题是:它是如何在标准库中完成的(或者至少是一个猜测),我如何才能相对轻松地为我的容器完成它?
标准中目前的措辞方式相当有趣。 [sequence.reqmts]/p15:
The extent to which an implementation determines that a type cannot be an input iterator is unspecified, except that as a minimum integral types shall not qualify as input iterators.
换句话说,实现只测试整数类型就足够了,但如果他们愿意,他们可以做更多。
使用 SFINAE 友好的 std::iterator_traits
(作为 LWG 问题投票进入 C++17 工作文件,但可能一直由大多数实现提供),例如,可以测试 std::iterator_traits<InputIterator>::iterator_category
是有效的,表示从 std::input_iterator_tag
派生的类型,类似于
template<class InputIt, std::enable_if_t<std::is_base_of<std::input_iterator_tag,
typename std::iterator_traits<InputIterator>::iterator_category>::value, int> = 0>
vector(InputIt first, InputIt last, const Allocator& alloc = Allocator());
请注意,这只是概念验证。标准库中的实际实现可能 1) 更复杂(例如,它可能基于迭代器类别进行优化 - 对于前向迭代器或更好的迭代器,它可以一次性为所有元素分配内存)和 2) 甚至比这更丑陋和填充下划线以避免名称冲突。