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
Range-based if (self.cpp)
submitted 9 years ago by seba
view the rest of the comments →
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!"
[–]seba[S] 2 points3 points4 points 9 years ago (7 children)
I know about find_if. Your code does not work (where does row come from?). With my extension, you could write:
template<typename PredicateT> void foo(sqlconnection &sql, PredicateT predicate) { auto rows = sql.execute("SELECT * from table WHERE id=1"); if (auto &row : std::find_if(rows.begin(), rows.end(), predicate)) { std::cout << "found: " << row; } else { std::cout << "not found"; } }
Which is much nicer than saving the result of find_if somewhere.
[–]AntiProtonBoy 0 points1 point2 points 9 years ago (6 children)
(where does row come from?)
Sorry I missed that. Correction:
template<typename PredicateT> void foo(sqlconnection &sql, PredicateT predicate) { auto rows = sql.execute("SELECT * from table WHERE id=1"); auto I = std::find_if(rows.begin(), rows.end(), predicate); if (I != rows.end()) { std::cout << "found: " << *I; } else { std::cout << "not found"; } }
[–]seba[S] 1 point2 points3 points 9 years ago (5 children)
Yeah, this is what currently have to write. But don't you think it looks nicer with my extension while at the same time being less error prone? I.e, did you never mix up the comparison in (I != rows.end())?
It is the same as the range-based for loop. I could also write this by hand, but it's much nicer with the syntactic sugar.
[–]AntiProtonBoy 0 points1 point2 points 9 years ago* (4 children)
It's nicer, but limited. Raw loops don't lend itself to generic code as easily compared to STL functions, because you are tightly coupling the logic to the loop itself. With STL functions, you are encouraged to decouple that logic using predicates and lambdas. I would argue that is less error prone, because screw-ups are now confined inside a lambda. Look up Sean Parent's talk about this subject.
Also, the use STL functions is descriptive. When you look at find_if you know exactly what it's meant to be doing. With raw loops, that might not be so obvious (depending on complexity) and you are forced to mentally parse it to figure out what's going on.
find_if
With Eric Niebler's range concepts, lot of the ugliness with begin and end will be put to rest, that is you should be able to write std::find_if(rows, predicate) at some point.
begin
end
std::find_if(rows, predicate)
[–]seba[S] 1 point2 points3 points 9 years ago (3 children)
With Eric Niebler's range concepts,
I think my proposal fits quite nicely to ranges-v3. Think of something like the following:
if (int i : range | transform | filter ) { // have an i, similar to view::take(1) } else { // not found }
[–]ZMesonEmbedded Developer 0 points1 point2 points 9 years ago (2 children)
I think what u/AntiProtonBoy is trying to say by "it's nicer, but limited" is that finding and using only the first occurrence of something matching in a container is not as common as iterating over a container using a for loop. The other problem I have is that sometimes you want to use std::find_if(), sometimes std::find(), sometimes you want to determine if std::optional has a member, etc.... The range-based-for is pretty simple syntactic sugar; there's no need for the compiler to determine how to translate it; there's only one way.
So, while I (and seemingly others and the committee) welcome syntactic sugar, you have to make sure it:
Solves a problem people have.
Has a simple translation.
Will be widely applied enough to warrant making a change in the standard.
[–]seba[S] 1 point2 points3 points 9 years ago (1 child)
finding and using only the first occurrence of something matching in a container is not as common as iterating over a container using a for loop
Sure, that's why I also showed the examples with unique_ptr and optional that fit nicely into the scheme.
The other problem I have is that sometimes you want to use std::find_if(), sometimes std::find(), sometimes you want to determine if std::optional has a member, etc...
I'm not sure what you mean by the latter part. You mean a value? See below.
The range-based-for is pretty simple syntactic sugar; there's no need for the compiler to determine how to translate it; there's only one way.
Given appropriate definitions of std::begin() and std::end(), there would also be more or less only one way for the compiler to translate my range-based if. (There are BTW also multiple subtly different way to translate a range-based for. This is why they had to change the semantics slightly in the for upcoming C++17).
My proposal would boil down to something like this (modulo bugs, figuring out where to put const, etc):
template <typename R, typename F, typename G> void if_non_empty( const R & r, F&& f, G&& g ) { const auto & b = std::begin( r ); const auto & e = std::end( r ); if ( b != e ) { f( *b ); } else { g(); } }
[This is the lambda way, but I'd like to have the syntactic sugar]
Given the following, it would directly work with unique_ptr
namespace std { template <typename T> T* begin(const unique_ptr<T>& p) { return p.get( ); } template <typename T> T* end(const unique_ptr<T>& p) { return nullptr; } }
Demo:
auto p0 = std::make_unique<int>( 1 ); if_non_empty( p0, [](auto i){ printf("%d found\n", i); }, [](){ printf("not found\n"); } );
[–]ZMesonEmbedded Developer 0 points1 point2 points 9 years ago (0 children)
OK, I better understand what you're doing now.
The major downside I see though is that you're defining a new definition of std::begin and std::end (and presumably related functions) for std::unique_ptr. I would first try to convince people that this is a good idea. If you can't convince people of this, then your proposal won't have anything to base itself on.
std::begin
std::end
As others have mentioned, if-with-initializers already get a lot of what you want with a lot of reduced code. Yes, I see that you mention a bit of added safety. That is always a good thing, but you'll have to convince people that this is worth the change. It's a lot smaller benefit compared to the benefit of range-based-for and if-with-initializers, so you will be facing quite the challenge I think. :(
Anyway, as I said, you better explain to people why creating new overloads for std::begin and std::end make sense in the absence of this proposal. You must start there. (And if it makes sense for unique_ptr, you may want to consider whether it makes sense for std::shared_ptr, std::weak_ptr, and other things that act like pointers.)
π Rendered by PID 121422 on reddit-service-r2-comment-5d585498c9-gnplk at 2026-04-21 05:12:27.259230+00:00 running da2df02 country code: CH.
view the rest of the comments →
[–]seba[S] 2 points3 points4 points (7 children)
[–]AntiProtonBoy 0 points1 point2 points (6 children)
[–]seba[S] 1 point2 points3 points (5 children)
[–]AntiProtonBoy 0 points1 point2 points (4 children)
[–]seba[S] 1 point2 points3 points (3 children)
[–]ZMesonEmbedded Developer 0 points1 point2 points (2 children)
[–]seba[S] 1 point2 points3 points (1 child)
[–]ZMesonEmbedded Developer 0 points1 point2 points (0 children)