C++98 容器定义了两种迭代器,::iterator
s 和 ::const_iterators
.一般来说,像这样:
struct vec{
iterator begin() ;
const_iterator begin() const;
};
在 C++11 中,这部分设计似乎没有改变。问题是,
为了一致性和实际目的,添加
::move_iterator
是否有意义?也一样? 或者它是一个矫枉过正。我可以想象,如果可能的话,右值容器可能会 move 它们的元素。
class vec{
iterator begin() &;
const_iterator begin() const&;
move_iterator begin() &&;
};
如果我理解正确,可以在简单的情况下这样实现: auto vec::begin() &&{return std::make_move_iterator(this->begin());}
当然,普通迭代器可以转换为 move 迭代器(使用
std::make_move_iterator
),但是动机是通用代码。例如,使用 move 迭代器,这将在没有条件的情况下非常优雅地实现,具体取决于参数是左值还是右值。
template<class Container, class T = Container::value_type>
void transport_first(Container&& c, std::vector<T>& v){
v.emplace_back(*std::forward<Container>(c).begin());
}
请注意,如果可能,此代码不会产生不必要的副本。没有
move_iterators
怎么实现?由 begin
生成.我也意识到这个问题几乎适用于容器的任何访问器,例如,
operator[]
, front()
和 back()
. template<class Value>
class vec{
using value_type = Value;
using reference = Value&;
using const_reference = Value const&;
using rvalue_reference = Value&&; // NEW!
reference front() &{...}
rvalue_reference front() &&{...} // NEW!
const_reference front() const&{...}
};
也许容器应该在 C++11 中从头开始重新设计。他们的设计正在显示它的时代。
有一个提议,自动推导出
(*this)
的(decl)类型基本上免费拥有 begin (和其他成员函数)的所有相应重载。https://youtu.be/yB4E-SzQPdI?t=4131
最佳答案
STL 容器旨在与 STL 算法结合使用。当前在 STL 中找到的通用算法处理迭代器,但您的模板函数 transport_first
:
template<class Container, class T = Container::value_type>
void transport_first(Container&& c, std::vector<T>& v){
v.emplace_back(*std::forward<Container>(c).begin());
}
由基于容器的代码组成,即:它在容器而不是迭代器上运行。多亏了概念,我们也许能够在 C++20 的 STL 中找到这样的基于容器的算法。
通用
transport_first
算法的“类似 STL 的方法”实际上是:template<typename InIt, typename OutIt>
void transport_first(InIt src, OutIt dst) {
*dst = *src;
}
遵循这种方法(即:迭代器而不是容器),当涉及到泛型代码时,是否使用
move_iterator
可以简单地在“最顶层”泛型算法处确定,因为传递的迭代器被进一步复制(即:被传递值到“基础”算法中)。此外,与上面基于迭代器的
transport_first
不同,STL 充满了基于迭代器对的算法(例如:std::copy
)来实现范围。这个接口(interface)使得在右值上重载那些容器成员函数没有什么吸引力,因为正如 this other answer 中已经说明的那样,这些重载的成员函数将在未命名(非 const
)容器对象上被调用,并且未命名的容器对象仅限于使用在单个表达式中,通过在同一容器对象上调用 begin()
和 end()
成员函数来阻碍迭代器对的创建。对于容器来说真正有意义的是拥有新的成员函数来返回相应的
move_iterator
对象:move_iterator Container<T>::mbegin();
move_iterator Container<T>::mend();
这只是调用
std::make_move_iterator
的快捷方式,成员函数返回的值返回 iterator
。成员函数 mbegin()
将在基于迭代器的 transport_first
中用作:transport_first(coll.mbegin(), std::back_inserter(vec));
相应的函数模板
std::mbegin()
和 std::mend()
也有意义:transport_first(std::mbegin(coll), std::back_inserter(vec));
关于c++11 - move 容器的迭代器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48915905/