我正在制作某种容器,我想模仿 std::vector
的界面.但是,我很难理解如何 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.
我了解它是如何完成的(我想是标签分派(dispatch)或模板特化),但我不知道 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)中的概念与否,我不知道如何为我的容器做到这一点。
因此我的问题是:它是如何在标准库中完成的(或者至少是一个猜测),以及我如何相对容易地为我的容器完成它?
最佳答案
标准中目前的措辞方式相当有趣。 [序列.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) 甚至比这更丑陋和填充下划线以避免名称冲突。
关于c++ - std::vector 构造函数采用一对迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28529376/