[cfe-dev] Range for loop and namespace std

Rahul Jain 1989.rahuljain at gmail.com
Fri Sep 13 14:23:19 PDT 2013


Thanks Richard :)


On Sat, Sep 14, 2013 at 2:51 AM, Richard Smith <richard at metafoo.co.uk>wrote:

> 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/20130914/1c6e4250/attachment.html>


More information about the cfe-dev mailing list