[cfe-dev] Range for loop and namespace std

James Dennett james.dennett at gmail.com
Fri Sep 13 13:34:06 PDT 2013


On Fri, Sep 13, 2013 at 1:19 PM, Rahul Jain <1989.rahuljain at gmail.com> wrote:
>
> Hi all,
>
> Please consider the following code which happens to be a gcc testsuite
> testcase:
>
>
> struct iterator
> {
>     int x;
>     explicit iterator(int v) :x(v) {}
>     iterator &operator ++() { ++x; return *this; }
>     int operator *() { return x; }
>     bool operator != (const iterator &o) { return x != o.x; }
> };
>
> // User defined container class
> struct container
> {
>     int min, max;
>     container(int a, int b) :min(a), max(b) {}
> };
>
> // Defintion of begin() and end() functions
> namespace std
> {
>     iterator begin(container &c)
>     {
>         return iterator(c.min);
>     }
>
>     iterator end(container &c)
>     {
>         return iterator(c.max + 1);
>     }
> }
>
> int main()
> {
>     container c(1,4);
>     for (int it : c)
>     {
>     }
> }
>
> Compiling it with clang gives the following error:
>
> range-for3.C:39:17: error: invalid range expression of type 'container'; no
> viable 'begin' function available
>     for (int it : c)
>                 ^ ~
> 1 error generated.
>
> clang version details: clang version 3.4 (trunk 186087)
> Target: i386-pc-linux-gnu
> Thread model: posix
>
> My question is: Is it legal to define the begin() and end() functions in the
> namespace std scope?

No.  It's not legal for user code to add anything to ::std apart from
specializations of existing entities (and the most promising
std::begin has a return type that depends on a member .begin().)

I've a feeling that the mention of std:: as an associated namespace is
now useless, given that arrays are special-cased in the language
rules, any type with member begin()/end() doesn't do the ADL, and
users can't legally add a std::begin for any type that doesn't have
member begin() .  I don't know if we have an open core language issues
for that.  (In an older proposed version of range-base for, it would
always use the ADL version, and we needed that to search in std to
support arrays and to default to using member begin/end.  The current
rules were one of the last significant changes in C++11.)

-- James



More information about the cfe-dev mailing list