gpt4 book ai didi

C++11 强制转换指向 shared_ptr 对象容器的常量迭代器

转载 作者:搜寻专家 更新时间:2023-10-31 00:40:10 25 4
gpt4 key购买 nike

我有一个元素类型为 const std::shared_ptr<MyClass> 的 STL 容器.

我想为用户提供两种迭代器类型:

  1. MyContainer::iterator

类型定义为 std::vector<const std::shared_ptr<MyClass>>::iterator(应与 std::vector<const std::shared_ptr<const MyClass>>::const_iterator 类型相同

  1. MyContainer::const_iterator

类型定义为 std::vector<const std::shared_ptr<const MyClass>>::iterator(应与 std::vector<const std::shared_ptr<const MyClass>>::const_iterator 类型相同

换句话说,我希望“const”指的是MyClass常量,不是 shared_ptr常数。我找到的获取第二个迭代器类型的解决方案是获取第一个,这很简单(例如使用 vector::begin ),然后使用 static_cast 将其转换为第二个类型(fixme:无需使用 const_cast,因为我添加的是常量,而不是删除它)。

这是实现该目标的常见良好设计方法,还是有更好/更常见的方法?

最佳答案

typedefed as std::vector<const std::shared_ptr<MyClass>>::iterator (which should be the same type as std::vector<std::shared_ptr<const MyClass>>::const_iterator

但它可能不是同一类型。迭代器不仅仅是指针。如果iteratorconst_iterator类型在 vector 中定义那么它们是完全不相关的类型:

template<typename T>
class vector
{
class iterator;
class const_iterator;
// ...

vector<const int>是与 vector<int> 不同的类型因此它们的嵌套类型也不同。就编译器而言,它们是完全不相关的类型,即你不能只移动 const。绕到此类型中的任何一点并获得兼容的类型:

vector<const shared_ptr<const T>>::iterator

您不能使用 const_cast在不相关的类型之间进行转换。您可以使用 static_cast转换 vector<T>::iteratorvector<T>::const_iterator但这并不是真正的强制转换,您是从前者构造后者,这是允许的,因为标准要求进行这种转换。

您可以转换 shared_ptr<const T>shared_ptr<T>const_pointer_cast<T>但同样只是因为它被定义为按标准工作,而不是因为类型本质上是兼容的,也不是因为它像普通的指针一样“正常工作”。

vector的迭代器不提供您想要的深度常量,您需要自己编写,但这并不难:

class MyClass { };

class MyContainer
{
typedef std::vector<std::shared_ptr<MyClass>> container_type;

container_type m_cont;

public:

typedef container_type::iterator iterator;

class const_iterator
{
typedef container_type::const_iterator internal_iterator;
typedef std::iterator_traits<internal_iterator> internal_traits;

const_iterator(internal_iterator i) : m_internal(i) { }
friend class MyContainer;

public:

const_iterator() { }
const_iterator(iterator i) : m_internal(i) { }

typedef std::shared_ptr<const MyClass> value_type;
typedef const value_type& reference;
typedef const value_type* pointer;
typedef internal_traits::difference_type difference_type;
typedef internal_traits::iterator_category iterator_category;

const_iterator& operator++() { ++m_internal; return *this; }
const_iterator operator++(int) { const_iterator tmp = *this; ++m_internal; return tmp; }

reference operator*() const { m_value = *m_internal; return m_value; }
pointer operator->() const { m_value = *m_internal; return &m_value; }

// ...

private:
internal_iterator m_internal;
mutable value_type m_value;
};

iterator begin() { return m_cont.begin(); }
const_iterator begin() const { return const_iterator(m_cont.begin()); }

// ...
};

该迭代器类型缺少一些东西(operator--operator+),但它们很容易添加,遵循与已经展示的相同的想法。

要注意的关键点是为了 const_iterator::operator*要返回引用,需要有一个 shared_ptr<const MyClass>作为迭代器成员存储的对象。该成员充当 shared_ptr<const MyClass> 的“缓存”值,因为底层容器的实际元素是不同的类型,shared_ptr<MyClass> ,因此您需要在某处缓存转换后的值,以便可以返回对它的引用。注意这样做稍微违反了迭代器要求,因为以下内容没有按预期工作:

MyContainer::const_iterator ci = c.begin();
const shared_ptr<const MyClass>& ref = *ci;
const MyClass* ptr = ref.get();
++ci;
(void) *ci;
assert( ptr == ref.get() ); // FAIL!

断言失败的原因是 *ci不返回对容器底层元素的引用,而是返回迭代器的一个成员,该成员通过以下增量和取消引用进行修改。如果此行为 Not Acceptable ,则需要从迭代器返回一个代理而不是缓存一个值。或者返回 shared_ptr<const MyClass>const_iterator被取消引用。 (很难做到 100% 正确是 STL 容器不尝试对深度常量建模的原因之一!)

boost::iterator_adaptor 为您完成了很多定义您自己的迭代器类型的工作。实用程序,所以上面的例子只对说明有用。使用该适配器,您只需执行此操作即可获得具有所需行为的自定义迭代器类型:

struct iterator
: boost::iterator_adaptor<iterator, container_type::iterator>
{
iterator() { }
iterator(container_type::iterator i) : iterator_adaptor(i) { }
};

struct const_iterator
: boost::iterator_adaptor<const_iterator, container_type::const_iterator, std::shared_ptr<const MyClass>, boost::use_default, std::shared_ptr<const MyClass>>
{
const_iterator() { }
const_iterator(iterator i) : iterator_adaptor(i.base()) { }
const_iterator(container_type::const_iterator i) : iterator_adaptor(i) { }
};

关于C++11 强制转换指向 shared_ptr 对象容器的常量迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15164330/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com