1

一般背景:

我正在尝试构建一个容器,它将充当运行时定义维度的多维数组的包装器 - 事实上,底层数组当然是总大小的一维数组。主要部分是operator []返回子数组的包装器。

由于容器需要迭代器,我目前正在该容器上实现迭代器,包括Container::iteratorContainer::const_iterator. 我努力模仿标准容器迭代器,它们应该尊重随机访问和输出迭代器的所有要求。

我已经注意到以下要求:

  • 公共默认构造函数
  • (当然是复制和移动语义)
  • iterator从 an到 a 的隐式转换const_iterator
  • iterator 和 const_interator 应该是可比较的

具体上下文:

标准容器迭代器根本不提供从 aconst_iterator到 a 的转换iterator,因为删除 const 可能很危险。我已经搜索过这个问题并找到了如何删除 const_iterator 的常量?其中答案提出了不同的技巧来从运算符中删除常量。所以我现在想知道是否应该在指针上实现从 const_iterator 到迭代器ala的显式转换。 const_cast

问题:

const_iterator实现从 a到 a的显式转换有哪些风险(非常量) iterator,它与链接问题的解决方案有何不同(为了便于阅读,复制到此处):

  • 使用提前和距离(我的随机访问迭代器中的恒定时间)

    iter i(d.begin());
    advance (i,distance<ConstIter>(i,ci));
    
  • 使用擦除:

    template <typename Container, typename ConstIterator>
    typename Container::iterator remove_constness(Container& c, ConstIterator it)
    {
        return c.erase(it, it);
    }
    

作为参考,这里是我的迭代器的简化和部分实现:

// Base for both iterator and const_iterator to ease comparisons
template <class T>
class BaseIterator {
protected:
    T *elt;          // high simplification here...
    BaseIterator(T* elt): elt(elt) {}
    virtual ~BaseIterator() {}

public:
    bool operator == (const BaseIterator& other) {
        return elt == other.elt;
    }
    bool operator != (const BaseIterator& other) {
        return ! operator == (other);
    }
    // other comparisons omitted...

    BaseIterator& add(int n) {
        elt += n;
        return *this;
    }  
};

// Iterators<T> in non const iterator, Iterator<T, 1> is const_iterator
template <class T, int cnst=0, class U= typename std::conditional<cnst, const T, T>::type >
class Iterator: public BaseIterator<T> {
    using BaseIterator<T>::elt;

public:
    using value_type = U;
    using reference = U*;
    using pointer = U&;
    using difference_type = int;
    using iterator_category = std::random_access_iterator_tag;

    Iterator(): BaseIterator<T>(nullptr);
    Iterator(T* elt): BaseIterator<T>(elt) {}

    // conversion from iterator to const_iterator
    template <class X, typename = typename std::enable_if<
        (cnst == 1) && std::is_same<X, T>::value>::type>
    Iterator(const BaseIterator<X>& other): BaseIterator<X>(other) {};

    // HERE: explicit conversion from const_iterator to non const
    template <class X, typename = typename std::enable_if<
        std::is_same<X, T>::value && (cnst == 0)>::type>
    explicit Iterator(const Iterator<X, 1 - cnst>& other): BaseIterator<T>(other) {}

    // partial implementation below
    U& operator *() {
        return *elt;
    }
    U* operator ->() {
        return elt;
    }
    Iterator<T, cnst, U>& operator ++() {
        this->add(1);
        return *this;
    }
};
4

1 回答 1

2

您引用的两种方法都需要对容器进行非常量访问,因此您无法将 const 底层元素作为非常量访问。

你的建议没有,所以它可以是 UB[dcl.type.cv]

于 2018-06-15T13:22:40.287 回答