C++ 依赖于begin()函数的常量迭代器

C++ 依赖于begin()函数的常量迭代器,c++,templates,c++11,iterator,C++,Templates,C++11,Iterator,我尽量把情况简化 基本上,我有一个类,它表示一个动态的数组(这里显示为大小为4的类数组),其次是一个类,它是一个HashMap,并且有一个数组作为成员(这里由类条表示) 这两个类都实现了begin()和end(),因此您可以使用foreach循环来迭代所有元素 Array的迭代器类型只是T*和const T*的常量变量。 对于条有一个特殊的类迭代器,它可以正确地迭代数组的所有成员。 你现在应该看看我提供的课程,这样你就知道我在说什么了 但是现在,当我在const-bar对象上调用bar.begi

我尽量把情况简化

基本上,我有一个类,它表示一个动态的
数组
(这里显示为大小为4的
类数组
),其次是一个类,它是一个HashMap,并且有一个
数组
作为成员(这里由
类条
表示)

这两个类都实现了
begin()
end()
,因此您可以使用foreach循环来迭代所有元素

Array
的迭代器类型只是
T*
const T*
的常量变量。 对于
有一个特殊的
类迭代器
,它可以正确地迭代
数组
的所有成员。 你现在应该看看我提供的课程,这样你就知道我在说什么了

但是现在,当我在
const-bar
对象上调用
bar.begin()
时出现了一个问题


迭代器类自动(通过T::begin()的decltype)确定
ArrayIterator
ElementIterator
类型,因为在我的实际应用程序中,几乎所有内容都是模板化的,这就是为什么我事先不知道确切的类型

我发现问题在于
decltype(((T*)nullptr)->begin())
总是选择T的非常量begin()函数,这绝对有意义,因为我没有编写
(const T*)nullptr

如果我现在从const上下文调用它,它将无法将
const T*
data.last().end()
一样分配给decltype的内部
T*
,而decltype实际上应该是
const T*

我可以通过声明第二个类
construtator
来解决这个问题,该类的所有操作都与非常量类完全相同,但在decltype语句中使用
(const Array*)nullptr
(const T*)nullptr

那么,如果不复制整个Bar::Iterator类,我能做什么呢


简化代码:

template<class T>
class Array
{
    T data[4];

    T last() { return data[3]; }


    T* begin()             { return data; };
    T* end()               { return data + 4; };

    const T* begin() const { return data; };
    const T* end() const   { return data + 4; };
}

template<class T>
class Bar
{
    class Iterator
    {
        using ArrayIterator = decltype(((Array<T>*)nullptr)->begin());
        using ElementIterator = decltype(((T*)nullptr)->begin());

        Iterator(const ArrayIterator& beg, const ArrayIterator& end)
        {
            //initialize the iterator to the first element of the first array
            //(and rembember end)
        };

        Iterator(const ElementIterator& cur)
        {
            //initialize the iterator to the current element
        };

        //++ will iterate go to next element and eventually jump to the next array.
        //== returns true if the current element is the same
    };

    Array<T> data;

    Iterator begin()       { return Iterator(data.begin(), data.end()); };
    Iterator end()         { return Iterator(data.last().end()); };

    Iterator begin() const { return Iterator(data.begin(), data.end()); };
    Iterator end() const   { return Iterator(data.last().end()); };
};
模板
类数组
{
T数据[4];
T last(){返回数据[3];}
T*begin(){返回数据;};
T*end(){返回数据+4;};
常量T*begin()常量{返回数据;};
常量T*end()常量{返回数据+4;};
}
模板
分类栏
{
类迭代器
{
使用ArrayIterator=decltype(((Array*)nullptr)->begin();
使用ElementIterator=decltype(((T*)nullptr)->begin();
迭代器(常量数组迭代器和beg、常量数组迭代器和end)
{
//将迭代器初始化为第一个数组的第一个元素
//(请记住,月底)
};
迭代器(常量元素迭代器&cur)
{
//将迭代器初始化为当前元素
};
//++将迭代转到下一个元素并最终跳转到下一个数组。
//==如果当前元素相同,则返回true
};
阵列数据;
迭代器begin(){返回迭代器(data.begin(),data.end());};
迭代器end(){返回迭代器(data.last().end());};
迭代器begin()常量{返回迭代器(data.begin(),data.end());};
迭代器end()常量{返回迭代器(data.last().end());};
};

实际上,您必须实现
构造函数。例如,请参见标准容器,如
vector
list
,其中既有
iterator
又有
const\u iterator
,它们是不同的类。保持正确有时很难。但是,您可以通过使用模板或const_cast(例如,请参阅Scott Myers Efficient C++)来避免代码复制。

不要为此使用const_cast。