Blog Archive for / 2019 / 02 /
Begin and End with range-based for loops
Saturday, 23 February 2019
On slack the other day, someone mentioned that lots of companies don't use range-based for
loops
in their code because they use PascalCase
identifiers, and their containers thus have Begin
and
End
member functions rather than the expected begin
and end
member functions.
Having recently worked in a codebase where this was the case, I thought it would be nice to provide a solution to this problem.
The natural solution would be to provide global overloads of the begin
and end
functions: these
are always checked by range-based for
if the member functions begin()
and end()
are not
found. However, when defining global function templates, you need to be sure that they are not too
greedy: you don't want them to cause ambiguity in overload resolution or be picked in preference to
std::begin
or std::end
.
My first thought was to jump through metaprogramming hoops checking for Begin()
and End()
members that return iterators, but then I thought that seemed complicated, so looked for something
simpler to start with.
The simplest possible solution is just to declare the functions the same way that std::begin()
and
std::end()
are declared:
template <class C> constexpr auto begin(C &c) -> decltype(c.Begin()) {
return c.Begin();
}
template <class C> constexpr auto begin(const C &c) -> decltype(c.Begin()) {
return c.Begin();
}
template <class C> constexpr auto end(C &c) -> decltype(c.End()) {
return c.End();
}
template <class C> constexpr auto end(const C &c) -> decltype(c.End()) {
return c.End();
}
Initially I thought that this would be too greedy, and cause problems, but it turns out this is fine.
The use of decltype(c.Begin())
triggers SFINAE, so only types which have a public member named
Begin
which can be invoked with empty parentheses are considered; for anything else these
functions are just discarded and not considered for overload resolution.
The only way this is likely to be a problem is if the user has also defined a begin
free function
template for a class that has a suitable Begin
member, in which case this would potentially
introduce overload resolution ambiguity. However, this seems really unlikely in practice: most such
function templates will end up being a better match, and any non-template functions are
almost certainly a better match.
So there you have it: in this case, the simplest solution really is good enough! Just include this
header and you're can
freely use range-based for
loops with containers that use Begin()
and End()
instead of
begin()
and end()
.
Posted by Anthony Williams
[/ cplusplus /] permanent link
Tags: cplusplus, for, range
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
ACCU 2019 presentation and book signing
Thursday, 21 February 2019
The ACCU 2019 conference is running from 9th-13 April 2019, in Bristol, UK.
This year I will be presenting "Here's my number; call me, maybe. Callbacks in a multithreaded world" on 11th April. The abstract is:
A common pattern in multithreaded applications is the use of callbacks, continuations and task pipelines to divide the processing of data across threads. This has the benefit of ensuring that threads can quickly move on to further processing, and can minimize blocking waits, since tasks are only scheduled when there is work to be done.
The downside is that they can weave a tangled web of connections, and managing object lifetimes can now become complicated.
This presentation will look at ways of managing this complexity and ensuring that your code is as clear as possible, and there is no possibility of dangling references or leaked objects.
I will also be signing copies of the second edition of my book C++ Concurrency In Action now that it is finally in print.
I look forward to seeing you there!
Posted by Anthony Williams
[/ news /] permanent link
Tags: C++, accu, ccia, book
Stumble It! | Submit to Reddit | Submit to DZone
If you liked this post, why not subscribe to the RSS feed or Follow me on Twitter? You can also subscribe to this blog by email using the form on the left.
Design and Content Copyright © 2005-2024 Just Software Solutions Ltd. All rights reserved. | Privacy Policy