[cfe-dev] Range for loop and namespace std

Richard Smith richard at metafoo.co.uk
Fri Sep 13 13:34:49 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);
>     }
>

This has undefined behavior. You can't add new declarations to namespace
std.

    iterator end(container &c)
>     {
>         return iterator(c.max + 1);
>     }
> }
>
> int main()
> {
>     container c(1,4);
>     for (int it : c)
>     {
>

This test is wrong, per DR1442:

http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1442


>     }
> }
>
> 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. See 17.6.5.2.1/1:

"The behavior of a C++ program is undefined if it adds declarations or
definitions to namespace std or to a namespace within namespace std unless
otherwise specified."

(The "unless otherwise specified" cases don't apply here.)


> The standard says:
>
> 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 with argument-dependent
> lookup (3.4.2). For the purposes of this name lookup, namespace std is an
> associated namespace.
>
It does not say this any more :)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130913/2b3c5128/attachment.html>


More information about the cfe-dev mailing list