Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.std.c++ > #514

Re: Different begin and end types in range-based for

From Andy Lutomirski<luto@amacapital.net>
Newsgroups comp.std.c++
Subject Re: Different begin and end types in range-based for
Date 2012-05-04 14:51 -0700
Organization Sonic.Net
Message-ID <4FA44847.506@amacapital.net> (permalink)
References <4fa1a7ad$0$16133$742ec2ed@news.sonic.net> <jnulb7$4ov$1@dont-email.me>

Show all headers | View raw


On 05/04/2012 11:23 AM, Daniel Krügler wrote:
>  Am 03.05.2012 20:10, schrieb Andy Lutomirski:
>>   I'm not sure whether this is should be submitted as a DR or if I should
>>   just live with it, but it would be convenient to have more flexibility
>>   in implementing containers with range-based for.
>
>  This issue was discussed before C++11 was released, see below for details.
>
>>   6.5.4 [stmt.ranged] defines this statement:
>>
>>   for ( for-range-declaration : expression ) statement
>>
>>   as equivalent to:
>>
>>
>>   {
>>     auto&&    __range = digits();
>>     for ( auto __begin = begin-expr,
>>                __end = end-expr;
>>           __begin != __end;
>>           ++__begin ) {
>>       auto i = *__begin;
>>       statement
>>     }
>>   }
>>
>>   There is nothing in this definition that fundamentally requires that
>>   __begin and __end have the same type.  However, 7.1.6.4 [dcl.spec.auto]
>>   says:
>>
>>   7. If the list of declarators contains more than one declarator, the
>>   type of each declared variable is determined
>>   as described above. If the type deduced for the template parameter U is
>>   not the same in each deduction, the
>>   program is ill-formed.
>>
>>   Therefore, if the return types of begin-expr and end-expr are different,
>>   the program is ill-formed.  An alternative formulation that would be
>>   identical other than this restriction (as far as I can tell) would be:
>>
>>   {
>>     auto&&    __range = digits();
>>     auto __begin = begin-expr;
>>     auto __end = end-expr;
>>     for ( ;
>>           __begin != __end;
>>           ++__begin ) {
>>       auto i = *__begin;
>>       statement
>>     }
>>   }
>>
>>   For example:
>>
>>   #include<iostream>
>>
>>   struct digit_end {};
>>
>>   struct digit_iter
>>   {
>>     int i;
>>     void operator ++ () { ++i; }
>>     int operator * () const { return i; }
>>     bool operator != (digit_end) const { return i != 10; }
>>   };
>>
>>   struct digits
>>   {
>>     digit_iter begin() const { digit_iter it; it.i = 0; return it; }
>>     digit_end end() const { return digit_end(); }
>>   };
>>
>>   int main(int, char **)
>>   {
>>     using namespace std;
>>
>>     // for (auto i : digits()) cout<<    i<<    endl;  [ill-formed]
>>
>>     // Alternative formulation, which works in g++ 4.6
>>     {
>>       auto&&    __range = digits();
>>       auto __begin = begin(__range);
>>       auto __end = end(__range);
>>       for ( ;
>>             __begin != __end;
>>             ++__begin ) {
>>         auto i = *__begin;
>>         cout<<    i<<    endl;
>>       }
>>     }
>>
>>     return 0;
>>   }
>>
>>
>>   It seems to me that 6.5.4 [stmt.ranged] should either be changed to
>>   allow this use or should contain an example or explanatory note
>>   indicating that this use is explicitly disallowed.
>>
>>   This particular example is silly, but I have a container in real code
>>   for which there is no efficient way to implement a true end() function,
>>   but checking whether at iterator is at the end is very simple.
>>
>>   (This idea is not new.  The same issue is mentioned in
>>   http://cxxpanel.org.uk/ballotcomment/526 but AFAICT was never submitted
>>   anywhere.)
>
>  This issue *was* submitted, this is national body comment GB 27, see
>
>  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3296.html
>
>  or here:
>
>  http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3289.pdf
>
>  At that time the range-for-loop was intensively discussed and no
>  consensus was found for this change. One further reason for not applying
>  this change was because the library algorithms also use a homogeneous
>  iterator model and the same applied to the concept models that were
>  considered just before.
>
>  Now, after the dust has settled and real implementations do exist, there
>  might be a good time to consider an extension of the current rules. If
>  you are interested in this I suggest to work on a proposal for that new
>  feature.

How do I go about submitting a proposal like that?

This idea is made a bit uglier by the fact (that I mis-remebered) that
begin(__range) and end(__range) are tried after .begin() and .end().  I
had imagined a container that implemented C++98-style .begin() and
.end() but had non-member begin and end that used different types and
were more efficient.

This can add to my fun as I masochistically try to maintain a decently
large code base in a language that just got standardized using compilers
that are a little bit behind :)

--Andy


-- 
[ comp.std.c++ is moderated.  To submit articles, try posting with your ]
[ newsreader.  If that fails, use mailto:std-cpp-submit@vandevoorde.com ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]

Back to comp.std.c++ | Previous | NextPrevious in thread | Next in thread | Find similar


Thread

Different begin and end types in range-based for Andy Lutomirski <luto@amacapital.net> - 2012-05-03 11:10 -0700
  Re: Different begin and end types in range-based for Daniel Krügler<daniel.kruegler@googlemail.com> - 2012-05-04 11:23 -0700
    Re: Different begin and end types in range-based for Andy Lutomirski<luto@amacapital.net> - 2012-05-04 14:51 -0700
    Re: Different begin and end types in range-based for Andy Lutomirski <luto@amacapital.net> - 2012-05-04 23:01 -0700

csiph-web