我正在制作某种容器,我想模仿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:
如果InputIt是整数类型,则此构造函数与overload(2)具有相同的效果。
我理解它是如何完成的(我认为是标签调度或模板专业化),但我不知道在C ++ 11中如何实现新行为:
如果InputIt满足InputIterator,则此重载仅参与重载解析,以避免与重载(2)的歧义。
这是某种SFINAE技巧吗?我不明白SFINAE如何在这里工作。而且,既然概念与C ++ 11(也不是C ++ 14)中的概念不同,我根本不知道如何为我的容器做到这一点。
因此我的问题是:它是如何在标准库中完成的(或者至少是一个猜测),我怎样才能相对容易地为我的容器做到这一点?
答案 0 :(得分:6)
目前在标准中措辞的方式相当有趣。 [sequence.reqmts] / P15:
实现确定类型不能的程度 输入迭代器未指定,除了作为最小积分 类型不应作为输入迭代器。
换句话说,实现仅测试整数类型就足够了,但如果他们愿意,他们可以做更多。
对于SFINAE友好std::iterator_traits
(投票进入C ++ 17工作文件作为LWG问题,但可能一直由大多数实现提供),例如,人们可能会测试{{1} }是有效的,表示从std::iterator_traits<InputIterator>::iterator_category
派生的类型,类似于
std::input_iterator_tag
请注意,这只是一个概念验证。标准库中的实际实现可能是1)更复杂(例如,它可以基于迭代器类别进行优化 - 对于前向迭代器或更好,它可以一次性为所有元素分配内存)和2)甚至比这更丑陋。填充下划线以避免名称冲突。