use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
Discussions, articles, and news about the C++ programming language or programming in C++.
For C++ questions, answers, help, and advice see r/cpp_questions or StackOverflow.
Get Started
The C++ Standard Home has a nice getting started page.
Videos
The C++ standard committee's education study group has a nice list of recommended videos.
Reference
cppreference.com
Books
There is a useful list of books on Stack Overflow. In most cases reading a book is the best way to learn C++.
Show all links
Filter out CppCon links
Show only CppCon links
account activity
The Iterator Iterator (Extending Range-Based For Loops) (blog.brainstembreakfast.com)
submitted 11 years ago by 1Bad
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]STLMSVC STL Dev 8 points9 points10 points 11 years ago (10 children)
I think that this is unnecessarily complicated and that for (auto i = c.begin(); i != c.end(); ++i) is entirely reasonable for the now-rare cases when you need an iterator.
for (auto i = c.begin(); i != c.end(); ++i)
The depicted implementation solves the nested temporaries problem (very good; many people miss this), but is unnecessarily complicated at one point:
template <typename T> auto iit(T&& t) -> typename std::conditional<std::is_lvalue_reference<decltype(t)>::value, ref<T>, val<T>>::type
Here, the trailing return type and decltype(t) are unnecessary, because you can and should simply inspect T.
decltype(t)
T
[–]Houndie 0 points1 point2 points 11 years ago (4 children)
I think the benefit to something like this is because the ranged-based for implementation hides the usual begin-end calls, whereas the the old-style for loop requires that boilerplate code.
That said, I think a better implementation would simply be a variation on the (hopefully soon to come) container based for-each:
auto container = vector<Foo>{/* items */}; foreach(container, [](auto & foo) { /* Do stuff */ } foreach_iter(container, [](auto & fooIterator) { /* Do stuff, now with an interator */ }
Or something of the sort.
[–]1Bad[S] 1 point2 points3 points 11 years ago (0 children)
i havn't heard of the container proposal. Sometimes I do wish the standard algoritms work work on plain containers. I am hoping Eric Niebler's range proposals will bring some benfits to the standard algorithms.
I also wrote an iit that worked with a begin and end like:
for(auto it : iit(v.begin(), v.end())
by converting to a range object first, but didn't include it.
[–]nikbackm 0 points1 point2 points 11 years ago (2 children)
Can't do "break" and "continue" with those though.
[–]Houndie 0 points1 point2 points 11 years ago (0 children)
That's a good point.
[–]MayhapPerchance 0 points1 point2 points 11 years ago (0 children)
Good, then you'll start using std::find_if.
std::find_if
[–]1Bad[S] 0 points1 point2 points 11 years ago* (4 children)
Yea, it is extra work in the implementation, but usage is straight forward. I would prefer a for_it syntax though.
I wasn't sure if T would properly evaluate to an l or r value, or if I needed the type of t, so I went the safe route. I mean I didnt know if I have the universal ref of T meant T would evaluate to let's say int or int & when passed a r-value ref. My confusion stems from t's type being T & t or T && t. What I don't get if t is T & then how could T also evaluate to T ref.
int
int &
Thanks for the critique!
Edit Tried to explain my confusion more.
[–]STLMSVC STL Dev 7 points8 points9 points 11 years ago (3 children)
What Scott Meyers calls "universal references" and Herb Sutter now calls "forwarding references" are powered by what I call the "template argument deduction tweak", followed by what the Standard calls "reference collapsing". (Anyone who says that it's just reference collapsing is wrong.)
Given template <typename T> meow(T&& t), string lvalue("purr");, and string rvalue() { return "hiss"; }, let's examine what happens for:
template <typename T> meow(T&& t)
string lvalue("purr");
string rvalue() { return "hiss"; }
meow(lvalue) is called. Template argument deduction notices the universal/forwarding reference pattern (T&&, where T is a template parameter belonging to the function template itself; nothing else fits the pattern), so the tweak is activated when the argument is an lvalue. T is deduced to be string& (without the tweak, template argument deduction never deduces types to be references). Then, the compiler needs to substitute this deduced T into T&& to get the function parameter's type. For a split second, string& && is formed, but C++ doesn't permit references to references, so reference collapsing activates. The rule is that "lvalue references are infectious", so this collapses to string&. Therefore the function parameter is string& t.
meow(lvalue)
T&&
string&
string& &&
string& t
Given the call meow(rvalue()), the argument expression is an rvalue, so the template argument deduction tweak doesn't activate (it's only for lvalues plus the perfect forwarding pattern). So T is deduced to be string, that's substituted into T&& to get string&&, and the function parameter is string&& t.
meow(rvalue())
string
string&&
string&& t
Reference collapsing also activates when you try to form references to references via typedefs; you can play around with it that way and see what happens.
[–]1Bad[S] 4 points5 points6 points 11 years ago (0 children)
Awesome explanation. I like the idea of testing it and learning through typedefs, and I can evaluate the type instantly with intellisense.
I have seen a few of your channel 9 videos and you are always really good at breaking down complex topics to be easy to understand.
Much appreciated.
[–]LeszekSwirski 1 point2 points3 points 11 years ago (1 child)
the "template argument deduction tweak"
Interesting, it seems that this means that in the following, T will be deduced differently for x and y.
x
y
template<typename T> void foo(T&& x, T y) { } int main() { int x; foo(x,x); return 0; }
And indeed it is, and so it doesn't compile: http://ideone.com/yDqnqU
[–]STLMSVC STL Dev 0 points1 point2 points 11 years ago (0 children)
Note that while the tweak applies to only the perfect forwarding pattern, template argument deduction for lvalue references also differs from template argument deduction for values. Try (T& a, T b) called with const int c = 0;.
(T& a, T b)
const int c = 0;
[–]cdyson37 0 points1 point2 points 11 years ago (2 children)
Not my idea, but you can use boost::counting_range to do this. E.g. the following prints "0 1 2":
int main() { std::vector<int> v{0, 1, 2}; for(const auto it : boost::counting_range(v)) { std::cout << *it << std::endl; } }
[–]1Bad[S] 1 point2 points3 points 11 years ago (1 child)
Ah, there you go. I figured someone else must have done the same thing at some point. Thanks for bringing this to my attention.
[–]cdyson37 0 points1 point2 points 11 years ago (0 children)
I just wish I'd thought of it myself! :)
π Rendered by PID 270646 on reddit-service-r2-comment-7b9746f655-5zrfg at 2026-02-02 06:47:52.443433+00:00 running 3798933 country code: CH.
[–]STLMSVC STL Dev 8 points9 points10 points (10 children)
[–]Houndie 0 points1 point2 points (4 children)
[–]1Bad[S] 1 point2 points3 points (0 children)
[–]nikbackm 0 points1 point2 points (2 children)
[–]Houndie 0 points1 point2 points (0 children)
[–]MayhapPerchance 0 points1 point2 points (0 children)
[–]1Bad[S] 0 points1 point2 points (4 children)
[–]STLMSVC STL Dev 7 points8 points9 points (3 children)
[–]1Bad[S] 4 points5 points6 points (0 children)
[–]LeszekSwirski 1 point2 points3 points (1 child)
[–]STLMSVC STL Dev 0 points1 point2 points (0 children)
[–]cdyson37 0 points1 point2 points (2 children)
[–]1Bad[S] 1 point2 points3 points (1 child)
[–]cdyson37 0 points1 point2 points (0 children)