我正在写一个自己的容器类,遇到了一个我无法理解的问题.这是显示问题的裸骨样本.
它由一个容器类和两个测试类组成:一个使用std:vector的测试类,它可以很好地编译,第二个测试类试图以完全相同的方式使用我自己的容器类但是很难编译.
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
template <typename T>
class MyContainer
{
public:
class iterator
{
public:
typedef iterator self_type;
inline iterator() { }
};
class const_iterator
{
public:
typedef const_iterator self_type;
inline const_iterator() { }
};
iterator begin() {
return iterator();
}
const_iterator begin() const {
return const_iterator();
}
};
// This one compiles ok, using std::vector
class TestClassVector
{
public:
void test() {
vector<int>::const_iterator I=myc.begin();
}
private:
vector<int> myc;
};
// this one …Run Code Online (Sandbox Code Playgroud) 为何选择STL
std::iterator_traits<const T*>::value_type
Run Code Online (Sandbox Code Playgroud)
与...的类型相同
std::iterator_traits<T*>::value_type
Run Code Online (Sandbox Code Playgroud)
为什么它的设计是这样的?首先不应该是const T而第二个是T吗?你应该如何采用底层const正确类型的迭代器?我知道你可以编写自己的模板类和专业化并从中获取
std::iterator_traits<const T*>::pointer
Run Code Online (Sandbox Code Playgroud)
但不应该有一个成员typedef持有它吗?
参见,例如, http ://en.cppreference.com/w/cpp/container/map/erase
在C++ 03中有三个重载:
void erase( iterator pos );
void erase( iterator first, iterator last );
size_type erase( const key_type& key );
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,第一和第二过载改变为采取const_iterator,使得它们可与任一被调用iterator或const_iterator.第一次重载也通过在删除之后将迭代器返回到元素来改进:
iterator erase( const_iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );
Run Code Online (Sandbox Code Playgroud)
在C++ 17中,重新引入了非const重载:
iterator erase( const_iterator pos );
iterator erase( iterator pos );
void erase( const_iterator first, const_iterator last );
size_type erase( const key_type& key );
Run Code Online (Sandbox Code Playgroud)
为什么需要这个?它不加入为不等erase,也不是为insert …
我管理(对象的集合Collection的Real简单例子).然后我在我的集合上定义了迭代器.这意味着:iterator,const_iterator,reverse_iterator和const_reverse_iterator.在这个例子中,我只会注意iterator和const_iterator,其他两个非常相似.
之后,我想在我的集合中定义一个过滤器,它根据特定条件保留或不保留元素.例如,仅保留Real具有正值的实例.我也想在我保留的元素上迭代我的集合.
对于此示例,集合中的对象非常简单.目标只是拥有一个对象而不是一个本机类型:
struct Real
{
public:
double r;
};
Run Code Online (Sandbox Code Playgroud)
然后我定义我的集合而不必知道里面的真实容器:
class Collection
{
public:
typedef std::vector<Real>::iterator iterator;
typedef std::vector<Real>::const_iterator const_iterator;
private:
std::vector<Real> data;
public:
Collection() : data() {}
Collection(unsigned long int n) : data(n) {}
Collection(unsigned long int n, const Real& x) : data(n,x) {}
Collection::iterator begin() { return this->data.begin(); }
Collection::iterator end() { return this->data.end(); }
Collection::const_iterator begin() …Run Code Online (Sandbox Code Playgroud) 考虑下面的代码,
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
vector<int> value{22, 23, 25, 34, 99};
auto it = find(value.cbegin(), value.cend(), 25);
value.insert(it, 77);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这it是一个const_iterator.在插入之前,它指向25.插入后,它指向77.这不会被视为修改吗?
C++ 98容器定义了两种迭代器,::iterators和::const_iterators.一般来说,像这样:
struct vec{
iterator begin();
const_iterator begin() const;
};
Run Code Online (Sandbox Code Playgroud)
在C++ 11中,这部分设计似乎没有改变.问题是,
为了保持一致性和实际目的,添加::move_iterators也是有意义的吗?或者它是一种矫枉过正.
我可以想象一个右值容器可能会移动它们的元素.
class vec{
iterator begin() &;
const_iterator begin() const&;
move_iterator begin() &&;
};
Run Code Online (Sandbox Code Playgroud)
如果我理解正确,可以在简单的情况下实现:
auto vec::begin() &&{return std::make_move_iterator(this->begin());}
Run Code Online (Sandbox Code Playgroud)
当然,普通的迭代器可以转换为移动迭代器(带std::make_move_iterator),但动机是通用代码.
例如,使用移动迭代器,这将非常优雅地实现,没有条件,具体取决于参数是左值还是右值.
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());
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果可能,此代码不会产生任何不必要的副本.如何在没有move_iterators生成的情况下实现begin.
我也意识到这个问题几乎适用于容器的任何访问器,例如operator[],front()和back().
template<class Value>
class vec{
using value_type = Value;
using reference = Value&;
using …Run Code Online (Sandbox Code Playgroud) 我用迭代器编写了自己的容器模板.我如何实现const_iterator?
template <class T>
class my_container {
private:
...
public:
my_container() : ... { }
~my_container() { }
class iterator : public std::iterator<std::bidirectional_iterator_tag, T> {
public: ...
Run Code Online (Sandbox Code Playgroud) 我相信自从C++ 11以来erase,大多数容器的功能(例如std::vector)接受一个const_iteratoras参数:
iterator erase (const_iterator position);
Run Code Online (Sandbox Code Playgroud)
我的编译器(GCC 4.8和Clang 3.2,都使用GCC libstdc ++)仍然不允许我使用这样的功能,即使在编译时也是如此--std=c++11.
它是编译器/ libstdc ++错误,还是我做了坏事?这是一个示例代码:
#include <vector>
int main( )
{
std::vector<int> v;
v.push_back( 1 );
v.push_back( 2 );
v.push_back( 3 );
std::vector<int>::const_iterator i = v.begin();
while( i != v.end() ) {
i = v.erase( i );
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 假设我正在实现一个集合,例如std::vector。我需要实现iterator和const_iterator,但是一旦完成,iterator就const_iterator不能仅实现为iterator<const T>(T集合中的类型在哪里)?
一定有原因为什么它不起作用,因为有上百万个问题有关如何在实现时重用代码iterator,const_iterator但是没有一个说“仅const T作为类型使用”。
我正在尝试为我的迭代器和const_iterator类实现一个反向迭代器适配器,但有点麻烦.如果有人能指导我完成这一点,那将非常感激!
我的想法是我应该能够从我的rbegin()和rend()函数调用中创建一个反向迭代器
reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;
Run Code Online (Sandbox Code Playgroud)
我在课堂上使用以下typedef:
typedef btree_iterator<T> iterator;
typedef const_btree_iterator<T> const_iterator;
typedef reverse_btree_iterator<iterator> reverse_iterator;
typedef reverse_btree_iterator<const_iterator> const_reverse_iterator;
Run Code Online (Sandbox Code Playgroud)
如您所见,我希望能够使用模板创建反向迭代器,为reverse_iterator类提供迭代器或const_iterator.
不幸的是,有点我坚持......
下面是我目前拥有的类定义,但有错误.
template <typename I> class reverse_btree_iterator {
typedef ptrdiff_t difference_type;
typedef bidirectional_iterator_tag iterator_category;
public:
reverse_btree_iterator() : base_(I()) {}
template <typename T> reverse_btree_iterator(const btree_iterator<T>& rhs) : base_(rhs) {}
I base() { return base_; }
I::reference operator*() const;
I::pointer operator->() const;
I& operator++();
I operator++(int);
I& operator--();
I operator--(int);
bool operator==(const I& other) const;
bool …Run Code Online (Sandbox Code Playgroud)