TypeIA
TypeIA

Reputation: 17250

Range expression of range-based for loops to use const function overloads

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.

Upvotes: 0

Views: 1063

Answers (2)

nate
nate

Reputation: 1871

A simple template function as_const can make the cast not so ugly. I believe this is being added or was recently added to the standard library.

template <typename T> T const & as_const (T const & t) { return t; }

void f ()
{
    for (auto && x: as_const (y)) {}
}

Upvotes: 0

AlexD
AlexD

Reputation: 32576

But a const version of get_numbers() is available and could be used.

The best function is selected before accessibility is considered. The standard states (emphasis mine):

If a best viable function exists and is unique, overload resolution succeeds and produces it as the result. Otherwise overload resolution fails and the invocation is ill-formed. When overload resolution succeeds, and the best viable function is not accessible (Clause 11) in the context in which it is used, the program is ill-formed.

Upvotes: 3

Related Questions