如何在 C++ 模板中将 foo<const bar> 隐式转换为 const foo<bar>?

how to implicitly convert a foo<const bar> into a const foo<bar> in C++ template?

我正在制作我自己的向量容器,我正在尝试使用 C++98 标准实现一个像真实迭代器一样工作的迭代器。

这是家庭作业,所以我不想得到答案,只是提示我应该看哪里以及我应该学习什么才能解决这个问题。

所以基本上我是在努力使这段代码工作:

ft::vector<int> v (100, 100);
ft::vector<int>::iterator it = v.begin();
ft::vector<int>::const_iterator cit = it;

std::cout << (cit == it) << std::endl; //comparison 1 /// works
std::cout << (it == cit) << std::endl; //comparison 2 /// doesn't compile
std::cout << (cit + 1 == it + 1) << std::endl; //doesn't work
std::cout << (it + 1 == cit + 1) << std::endl; //doesn't work

iteratorconst_iterator 是这样的类型定义:

typedef typename ft::iterator_vector<value_type> iterator;
typedef typename ft::iterator_vector<const value_type> const_iterator;

值类型是传递给向量模板的类型。

直到我在迭代器模板中添加用户定义的转换运算符以将 iterator<const foo> 转换为 iterator<foo>(实际上正如@TedLyngmo 所指出的那样) 这是 operator iterator_vector<const value_type>() const { return _p; } 但是编译器说我现在需要能够将 iterator<const foo> 转换为 const iterator<foo> 而我不知道如何继续。

这是我的迭代器的实现:

template <class T>
class iterator_vector : public ft::iterator<std::random_access_iterator_tag, T> {

public:

    typedef             ft::iterator<std::random_access_iterator_tag, T>    iterator;
    typedef             ft::iterator_traits<iterator>                   iterator_traits;
    typedef typename    iterator_traits::difference_type                difference_type;
    typedef typename    iterator_traits::value_type                     value_type;
    typedef typename    iterator_traits::pointer                        pointer;
    typedef typename    iterator_traits::reference                      reference;
    typedef typename    iterator_traits::iterator_category              iterator_category;

    /*
    ** Member functions
    */

    iterator_vector(pointer p = 0) : _p(p) {}
    ~iterator_vector(void) {}

    operator iterator_vector<const value_type>() const { return _p; }

    iterator_vector& operator++() { ++_p; return *this; }
    iterator_vector operator++(int)
    {
        iterator_vector r = *this;
        ++_p;
        return r;
    }
    iterator_vector& operator--() { --_p; return *this; }
    iterator_vector operator--(int)
    {
        iterator_vector r = *this;
        --_p;
        return r;
    }
    iterator_vector operator+(size_t n) const { return iterator_vector(_p + n); }
    iterator_vector operator-(size_t n) const { return iterator_vector(_p - n); }
    iterator_vector& operator+=(size_t n) { _p += n; return *this; }
    iterator_vector& operator-=(size_t n) { _p -= n; return *this; }
    difference_type operator+(iterator_vector rhs) const { return _p + rhs._p; }
    difference_type operator-(iterator_vector rhs) const { return _p - rhs._p; }
    reference operator*(void) const { return *_p; }
    pointer operator->() const { return _p; }
    reference operator[](size_t n) const { return _p[n]; }
    bool operator==(const iterator_vector& rhs) const { return _p == rhs._p; }
    bool operator!=(const iterator_vector& rhs) const { return _p != rhs._p; }
    bool operator<(const iterator_vector& rhs) const { return _p > rhs._p; }
    bool operator>(const iterator_vector& rhs) const { return _p < rhs._p; }
    bool operator<=(const iterator_vector& rhs) const { return _p <= rhs._p; }
    bool operator>=(const iterator_vector& rhs) const { return _p >= rhs._p; }

    /*
    ** Non-member functions
    */

    friend iterator_vector operator+(size_t n, const iterator_vector& rhs) { return iterator_vector(rhs._p + n); }
    friend iterator_vector operator-(size_t n, const iterator_vector& rhs) { return iterator_vector(rhs._p - n); }

private:

    pointer _p;

};

从您在代码中关于失败的评论看来,您缺少一个比较函数,用于 iterator 位于左侧而 const_iterator 位于右侧。您可以添加这个免费功能:

template<typename T>
bool operator==(const iterator_vector<T>& lhs, const iterator_vector<const T>& rhs) {
    // just swap the order here and the implicit conversion from `iterator`
    // to `const_iterator` from `lhs` solves the rest:
    return rhs == lhs;
}

I added a user-defined conversion operator in my iterator template to convert iterator<const foo> into iterator<foo>

不,您以相反的方式添加了隐式转换。也就是说,从 iteratorconst_iterator - 这很好!


另一种方法是使两个迭代器 friends 不必实现类似的交换 lhsrhs适用于所有操作员的功能。模板中的运算符将变为:

// define these before your class template (borrowed from C++11):
template< class T > struct remove_const          { typedef T type; };
template< class T > struct remove_const<const T> { typedef T type; };
//... in your class template:
friend class iterator_vector<typename remove_const<T>::type>;
friend class iterator_vector<const T>;

template<typename U>
bool operator==(const iterator_vector<U>& rhs) const { return _p == rhs._p; }
template<typename U>
bool operator!=(const iterator_vector<U>& rhs) const { return _p != rhs._p; }
template<typename U>
bool operator<(const iterator_vector<U>& rhs) const { return _p > rhs._p; }
template<typename U>
bool operator>(const iterator_vector<U>& rhs) const { return _p < rhs._p; }
template<typename U>
bool operator<=(const iterator_vector<U>& rhs) const { return _p <= rhs._p; }
template<typename U>
bool operator>=(const iterator_vector<U>& rhs) const { return _p >= rhs._p; }