Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/136.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从迭代器构造常量迭代器_C++ - Fatal编程技术网

C++ 从迭代器构造常量迭代器

C++ 从迭代器构造常量迭代器,c++,C++,我正在为一些自定义容器(基于列表)实现一个简单的迭代器: 当我像这样使用迭代器时,它不会编译: #include <iostream> #include <vector> struct A { void func() { container<A>::const_iterator i = m_v.begin(); } container<A> m_v; }; int main() { A

我正在为一些自定义容器(基于列表)实现一个简单的迭代器:

当我像这样使用迭代器时,它不会编译:

#include <iostream>
#include <vector>

struct A
{
    void func()
    {
        container<A>::const_iterator i = m_v.begin();
    }

    container<A> m_v;
};

int main()
{
    A a;

    a.func();

    return 0;
}

因此,可以通过添加
const
来定义类型转换运算符,
const\u迭代器将转换为自身。但是看起来有点奇怪…

您可以简单地提供一个隐式转换运算符,将迭代器的非常量版本转换为常量版本。举个简单的例子:

template<class T>
class my_iter
{
public:
    // Non-const iterator can be implicitly converted to const
    operator my_iter<const T>() const {
        // Replace this with however your iterator is constructed
        return {};
    }
};
这仍然有一个缺点,即参数的
private
s不可访问。一个解决方法是使
迭代器成为
迭代器的
朋友类


无论使用哪种解决方案,都可以为
操作符重复该操作。您只需提供一个隐式转换操作符,将迭代器的非常量版本转换为常量版本。举个简单的例子:

template<class T>
class my_iter
{
public:
    // Non-const iterator can be implicitly converted to const
    operator my_iter<const T>() const {
        // Replace this with however your iterator is constructed
        return {};
    }
};
这仍然有一个缺点,即参数的
private
s不可访问。一个解决方法是使
迭代器成为
迭代器的
朋友类


无论使用哪种解决方案,都可以对
运算符重复此操作可能这是实现此操作的正确方法…使用
std::enable的转换运算符如何_if@Dmitriano没有必要。如果
T
const
,则转换运算符将永远不会起作用。编辑:我不确定你指的是哪两个不同的类。我想出来了!我定义了
运算符single\u iterator()const
@Dmitriano我已经修改了答案。我希望它能解决您的问题。是的,也许这是实现这一点的正确方法……那么使用
std::enable的转换运算符呢_if@Dmitriano没有必要。如果
T
const
,则转换运算符将永远不会起作用。编辑:我不确定你指的是哪两个不同的类。我想出来了!我定义了
运算符single\u iterator()const
@Dmitriano我已经修改了答案。我希望它能解决您的问题。链接副本中的一些答案提到了从
迭代器
常量迭代器
的转换,但大多数答案都没有提到,而且这个问题比这个问题更一般。我不确定副本是否合适,但我不愿意删除它,因为我已经发布了一个答案,可能有偏见。@FrançoisAndrieux我想我添加了一条评论,解释了哪些答案特别针对它,但我现在没有看到。无论如何,尽管我认为这个问题是重复的,但你下面的答案还是很好的。链接副本中的一些答案提到了从
迭代器
常量迭代器
的转换,但大多数答案都没有,而且这个问题比这个问题更一般。我不确定副本是否合适,但我不愿意删除它,因为我已经发布了一个答案,可能有偏见。@FrançoisAndrieux我想我添加了一条评论,解释了哪些答案特别针对它,但我现在没有看到。无论如何,尽管我认为这个问题是重复的,你下面的回答还是很好的。
struct A
{
    operator A() { return *this;}
};

int main()
{
    A a;

    return 0;
}
template<class T>
class my_iter
{
public:
    // Non-const iterator can be implicitly converted to const
    operator my_iter<const T>() const {
        // Replace this with however your iterator is constructed
        return {};
    }
};
bool operator==(const my_iter<std::add_const_t<T>> & p_other) const 
{
    // Compare...
}
#include <type_traits>

template<class T>
class my_iter
{
public:
    // Non-const iterator can be implicitly converted to const
    operator my_iter<const T>() const {
        // Replace this with however your iterator is constructed
        return {};
    }

    bool operator==(const my_iter<std::add_const_t<T>> & p_other) const 
    {
        return state == p_other.state; // Works even if `state` is `private`
    }

private:
    // Some iterator implementation detail
    T * state = nullptr;

    // `iter<T>` and `iter<const T>` are friends of each other
    friend class my_iter<std::remove_const_t<T>>;
    friend class my_iter<std::add_const_t<T>>;
};
bool operator==(const my_iter<std::add_const_t<T>> & p_other) const 
{
    if constexpr (std::is_same_v<std::decay_t<decltype(p_other)>, my_iter<T>>) {
        // `*this` and `p_other` are both `const T` iterators
        // You may access the private members of both objects here
        return state == p_other.state; // Works even if `state` is `private`
    }
    else {
        // The `p_other` is not the same type as `*this`
        return static_cast<const my_iter<const T> &>(*this) == p_other;
    }
}