问题
I tried to overload (c)begin/(c)end functions for a class so as to be able to call C++11 range-based for loop.
It works in most of the cases, but I don't manage to understand and solve one :
for (auto const& point : fProjectData->getPoints()){ ... }
This line returns error:
Error C2662: 'MyCollection<T>::begin' : cannot convert 'this' pointer from 'const MyCollection' to 'MyCollection<T> &'
because fProjectData is a pointer to const. If I make it non-const, it does work. I don't understand why, considering that cbegin() & cend() are developped with exactness as begin() & end() functions.
Here are my functions developped (in the header file) in 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();
}
Any ideas?
回答1:
A range-based for loop (for a class-type range) looks up for begin and end functions. cbegin and cend are not considered at all:
§ 6.5.4 [stmt.ranged]/p1 *:
[...]
if
_RangeTis a class type, the unqualified-idsbeginandendare looked up in the scope of class_RangeTas 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)andend(__range), respectively, wherebeginandendare looked up in the associated namespaces (3.4.2). [ Note: Ordinary unqualified lookup (3.4.1) is not performed. — end note ]
For a const-qualified range the related member functions must be const-qualified as well (or should be callable with a const-qualified instance if the latter option is in use). You'd need to introduce additional overloads:
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
* the wording comes from C++14, but the differences are unrelated to the problem as it is stated
来源:https://stackoverflow.com/questions/31581880/overloading-cbegin-cend