Clan x86

Technical (Development, Security, etc.) => General Programming => Topic started by: nslay on January 07, 2014, 11:37:10 pm

Title: Lambdas and 'auto' types in C++11
Post by: nslay on January 07, 2014, 11:37:10 pm
Does anyone really think lambda expressions help C++? I think it's nice to be able to create functors on the fly, although it's not always readable.

STL has <algorithm> which includes algorithms like std::for_each and std::find_if that accept functors/functions. In the past you usually had to create a functor to use these which was typically more code than just writing your own for loop. I thought lambdas would make functions like std::for_each practical. However, which is more readable?

Code: [Select]
int sum = 0;
std::vector<int> vArray = { 1, 2, 3, 4, 5 }; // Yes, you can do this in C++11
std::for_each(std::begin(vArray), std::end(vArray), [&sum](int x) {
  sum += 2*x;
});

Or

Code: [Select]
int sum = 0;
std::vector<int> vArray = { 1, 2, 3, 4, 5 };
for (size_t i = 0; i < vArray.size(); ++i) {
  sum += 2*vArray[i];
}

Better yet!
Code: [Select]
int sum = 0;
std::vector<int> vArray = { 1, 2, 3, 4, 5 };
for (int x : vArray) {
  sum += 2*x;
}

I'm not seeing any elegant use of lambda expressions. Seeing functor definitions as parameters to other functions looks weird and messy. You could also just write a functor in an unnamed namespace to prevent namespace pollution. The functor could be named something intuitive like:
Code: [Select]
namespace {
  struct NickEquals {
    // ...
  };
} // only valid in this translation unit

auto itr = std::find_if(std::begin(vUsers), std::end(vUsers), NickEquals("nslay")); // Find If Nick Equals "nslay" ... reads nicely!

Another one I have mixed feelings about is the auto type specifier. Yes, it is very convenient to write, but it's not very readable.

Code: [Select]
auto thing = Blah(); // So, what does Blah() return? Oh, right, best go look in the header. Oh, and did I mention 'auto' also consumes constness and pointers too (but not references)? Blah() might return a pointer ... or maybe a const. You'd never guess that by looking at it though.

// Oh yeah, If I changed Blah()'s return type, maybe it still compiles and runs when it shouldn't.

for (auto &x : vArray) {
  // Wait, what is x again?
}

Anyone else have such thoughts?
Title: Re: Lambdas and 'auto' types in C++11
Post by: while1 on February 05, 2014, 10:45:26 pm
IMO the STL for_each() w/ lambdas is more readable than the traditional for loop for a trivial for loop where one iterates through summing the entirety of the data structure from beginning to end.  However, I consider the STL for_each() less readable than the new foreach loop syntax (yay for C++11!)  IMO, the STL for_each() and the new foreach loop both provide solutions to a shared problem- wasting time writing and reading trivial for loops.  The new foreach loop is the better solution though IMO and makes the STL for_each irrelevant (although there may be scenarios where it excels?)

I'd be more interested in the performance difference.  Correct me if I'm wrong, but the STL for_each() is going to be slowest of the three.

As to the readability the "auto" feature, or implicit typing of local variables (inferred by the compiler), I would say I also have mixed feelings about it.  C# has had this feature for years except it's "var" instead of "auto".  At first I wasn't too keen on using it at all, but I've found myself using it generally when the convenience in writeability outweighs the detriment to readability.  In other words, usually only when I one can infer the type by simply looking to the right of the assignment operator.  I agree though, it's a lot more complicated for C++ because of pointers and constness.  Although, I think that readability can be significantly mitigated by use of a modern IDE.