重载 (c)begin/(c)end

Overloading (c)begin/(c)end

我试图为 class 重载 (c)begin/(c)end 函数,以便能够调用 C++11 基于范围的 for 循环。

它适用于大多数情况,但我无法理解和解决一个问题:

for (auto const& point : fProjectData->getPoints()){ ... }

这一行returns错误:

Error C2662: 'MyCollection<T>::begin' : cannot convert 'this' pointer from 'const MyCollection' to 'MyCollection<T> &'

因为fProjectData是一个指向const的指针。如果我将它设为非常量,它就可以工作。我不明白为什么,考虑到 cbegin()cend() 是像 begin()end() 函数一样精确地开发的。

这是我在 MyCollection 中开发的函数(在头文件中):

/// \returns the begin iterator
typename std::list<T>::iterator begin() {
    return objects.begin();
}

/// \returns the begin const iterator
typename std::list<T>::const_iterator cbegin() const {
    return objects.cbegin();
}

/// \returns the end iterator
typename std::list<T>::iterator end() {
    return objects.end();
}

/// \returns the end const iterator
typename std::list<T>::const_iterator cend() const {
    return objects.cend();
}

有什么想法吗?

基于范围的 for 循环(对于 class 类型的范围)查找 beginend 函数。 cbegincend完全不考虑:

§ 6.5.4 [stmt.ranged]/p1 *:

[...]

  • if _RangeT is a class type, the unqualified-ids begin and end are looked up in the scope of class _RangeT as if by class member access lookup (3.4.5), and if either (or both) finds at least one declaration, begin-expr and end-expr are __range.begin() and __range.end(), respectively;

  • otherwise, begin-expr and end-expr are begin(__range) and end(__range), respectively, where begin and end are looked up in the associated namespaces (3.4.2). [ Note: Ordinary unqualified lookup (3.4.1) is not performed. — end note ]

对于 const 限定的范围,相关的成员函数也必须是 const 限定的(或者应该可以用 const 限定的实例调用,如果后一个选项是正在使用)。您需要引入额外的重载:

typename std::list<T>::iterator begin() {
    return objects.begin();
}

typename std::list<T>::const_iterator begin() const {
//                                            ~~~~^
    return objects.begin();
}

typename std::list<T>::const_iterator cbegin() const {
    return begin();
}

typename std::list<T>::iterator end() {
    return objects.end();
}

typename std::list<T>::const_iterator end() const {
//                                          ~~~~^
    return objects.end();
}

typename std::list<T>::const_iterator cend() const {
    return end();
}

DEMO


* 措辞来自 C++14,但差异与问题无关