如何将一个合适的const_iterator返回给非常量指针的集合?

时间:2015-03-08 22:06:23

标签: c++ gcc

我有一个类封装了一个指向类MyClass的指针的向量(指针代替实例,因为MyClass实际上是一个广泛的子类层次结构的基类,其实例保存在集合中)。向量不能保存const指针,因为该集合拥有对象并在其析构函数中删除它们。

此集合的用户应具有对集合中项目的只读访问权限。常规const_iterator不会在这里完成工作,因为它会允许班级用户修改项目,所以我做了这个typedef:

    class MyCollection
    {
    private:
        std::vector<MyClass*> backingCollection;
    public:
        typedef std::vector<MyClass const*>::const_iterator const_iterator;

MyCollection需要有一个begin和end方法来返回这些迭代器。但是,backingCollection.begin()会返回常规const_iterator,因此我不得不将一个看起来非常糟糕的演员组合在一起:

    inline const_iterator begin() const 
    { 
          return *reinterpret_cast<const_iterator*>(&this->backingCollection.begin());           
    }

当我仅在Visual Studio中编译项目时,这很好用,但是GCC讨厌它:

error: taking address of temporary [-fpermissive]

我不想仅仅因为这个而启用许可模式。

这里最好的解决方案是什么? const迭代器的整个想法是错误的吗?有没有更好的方法来转换迭代器?

3 个答案:

答案 0 :(得分:3)

使用.data()而不是begin,它返回指向const指针的指针,并隐式转换为指向const指向const的指针。对于end返回数据加上大小。

你丢失了调试工具,这就是它。

typedef MyClass const*const* const_iterator;

inline const_iterator begin() const { 
  return backingCollection.data();
}
inline const_iterator end() const { 
  return begin()+backingCollection.size();
}

答案 1 :(得分:0)

请注意,您获取临时的地址。我认为破解转换是一个坏主意(除非可能在非常短暂的实验代码中),但是如果你要坚持它,你所要做的就是不要使对象成为临时对象:put {{1}在一个局部变量中。

答案 2 :(得分:0)

一如既往,编译器是对的 :-)

您必须在 backing_collection 的地址上使用 reinterpret_cast,然后从重新解释的地址中返回 const_iterator。

using ConstCollection = const std::vector<const MyClass*>;

inline auto begin() const { 
  return reinterpret_cast<ConstCollection*>&backingCollection)->cbegin();
}

inline auto end() const { 
  return reinterpret_cast<ConstCollection*>&backingCollection)->cend();
}