[cfe-dev] Range for loop and namespace std

Richard Smith richard at metafoo.co.uk
Fri Sep 13 14:21:18 PDT 2013


On Fri, Sep 13, 2013 at 1:58 PM, Rahul Jain <1989.rahuljain at gmail.com>wrote:

> Thanks Richard and James for the quick revert.
> This resolution of the standard makes things clearer.
>
> So best practice would be to define begin() and end() as member functions
> of the user defined container class right?
>

The best practice would be to define these functions as member functions if
that makes sense, and as free functions in the enclosing namespace (so they
can be found by ADL) otherwise.


> On Sat, Sep 14, 2013 at 2:04 AM, Richard Smith <richard at metafoo.co.uk>wrote:
>
>> 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/dd849d79/attachment.html>


More information about the cfe-dev mailing list