[Development] Proposal: Deprecating platforms in Qt 5.6 that don't support lambda

Matthew Woehlke mw_triad at users.sourceforge.net
Thu Feb 19 20:51:32 CET 2015


On 2015-02-19 14:36, Thiago Macieira wrote:
> On Thursday 19 February 2015 12:07:04 Matthew Woehlke wrote:
>> On 2015-02-19 07:29, Daniel Teske wrote:
>>> Qt's container classes and C++11 range based for loop do not mix very
>>> well.
>>> Ranged based for uses std::begin(container), which if not overloaded calls
>>> container.begin(), which detaches.
>>
>> As an aside, the "correct" fix for this IMHO is for range-based for to
>> support a mechanism for marking the RHS 'const', whether or not it
>> otherwise would be so.
>>
>> Worst case, Qt could (should?) implement something like:
>>
>>   struct QConstWrapper<ContainerType>
>>   {
>>     ContainerType::const_iterator begin() const;
>>     ContainerType::const_iterator end() const;
>>     // remaining "magic" elided
>>   };
>>
>>   QConstWrapper<ContainerType> qConst(ContainerType const&);
>>
>> That said, note that range-based for also differs from foreach in that
>> the former operates on the original container, whereas the latter
>> operates on a copy.
> 
> It actually needs to be:
> 
> template <typename T> const T qConst(const T &t) { return t; }
> 
> It needs to create a copy and return it. There's a gotcha with range-based for 
> that it is defined in such a way that your temporaries may be destroyed before 
> the iteration. The standard defines it as:
> 
> {
> 	auto && __range = <your range>;
> 	for ( auto __begin = std::begin(__range),
> 			__end = std::end(__range);
> 			__begin != __end;
> 			++__begin ) {
> 		<for-range-declaration> = *__begin;
> 		<statement>
> 	}
> }
> 
> If you have a temporary in your right hand of the ':' it will get lifetime-
> extended by that __range reference. Any other temporaries will get destroyed.
> 
> That means a cast works and a copy works. Returning a reference doesn't.

You'll note that I did *not* return a reference.

Returning a copy may be okay for Qt since containers are COW (in fact,
your version would result in a range-based for that works much more like
Q_FOREACH, which is probably good for some cases). What I was aiming for
was rather a class that internally holds a reference to the container
(such class would be copyable) and forwards the calls to begin/end to
that container, such that in a range-based for it appears to *be* the
container, but forces use of const_iterator. Note that this would work
equally well for non-Qt containers, as long as they have 'IteratorType
{begin,end}() const' methods. (Trailing return specification may be
required to permit the container's iterator type to be unknown.)

I was initially thinking that this was perhaps simple enough to not be
worth it. Given your point, I am leaning more toward that it *would* be
valuable.

(I still think the best solution is for C++ to just accept 'const
<expr>' as a modifier to make the type of '<expr>' constant, regardless
of whether or not it was. This would allow things like 'for (auto item :
const container)', '(const this)->begin()', 'foo(const bar)', and so forth.)

-- 
Matthew




More information about the Development mailing list