Update, thanks to AlexD's answer: This question boils down to the language rules for selecting member function overloads, which is discussed in the following question: Calling a const function rather than its non-const version
When the range expression of a range-based for loop is a call to a member function with const
and non-const
overloads, it seems that the non-const
overload is selected. As a result, the following program does not compile:
#include <iostream>
#include <vector>
class foo {
public:
const std::vector<int>& get_numbers() const { return numbers; }
protected:
std::vector<int>& get_numbers() { return numbers; }
private:
std::vector<int> numbers;
};
int main() {
foo f;
for (int x : f.get_numbers()) std::cout << x << std::endl;
}
Diagnostic message from gcc 5.3:
error: ‘std::vector<int>& foo::get_numbers()’ is protected
But a const
version of get_numbers()
is available and could be used. We can force it to be used by using a const
reference to the foo
instance, like this:
int main() {
foo f;
const foo& g = f;
for (int x : g.get_numbers()) std::cout << x << std::endl;
}
Is there a better/easier way to tell the compiler that it can and should use the const
member function overload, without explicitly making a const
reference to the object?
There are some similar questions about making the range-based for loop use const
iterators, but I haven't found any questions about making the loop's range expression const
for the purposes of selecting function overloads.