c++ - 重载 (c)begin/(c)end

标签 c++ c++11 for-loop constants

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

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

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

此行返回错误:

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 循环(针对类类型范围)查找 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,但差异与问题无关

关于c++ - 重载 (c)begin/(c)end,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31581880/

相关文章:

c++ - 为什么我收到警告 "C4199 two-phase name lookup is not supported for C++/CLI, C++/CX, or openmp"?

c++ - 如何在C++11中获取指针的类型

sql - 为什么我的查询结果随机返回?

javascript - 不要在循环错误中创建函数,我无法修复

c++ - 解决 C++ 名称冲突

c++ - 500,000 个已排序整数数组的 C++ 快速排序算法中的段错误

c++ - nullptr 是否释放指针的内存?

c++ - 作为模板参数的(任何类型的)值列表

c++ - C++03 throw() 说明符 C++11 noexcept 之间的区别

windows - 修改for循环批处理文件中的变量