Jump to content

  • Log In with Google      Sign In   
  • Create Account

Banner advertising on our site currently available from just $5!


1. Learn about the promo. 2. Sign up for GDNet+. 3. Set up your advert!


I don't get c++11.


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
35 replies to this topic

#1 doyleman77   Members   -  Reputation: 366

Like
9Likes
Like

Posted 18 February 2014 - 09:43 PM

Pretty comfortable with my c++ code now; I get classes, I get using templates and STL, smart pointers, and to an extent, exceptions. What I don't get is most of the new 2011 standard. Lambdas confuse me, in both their syntax and their purpose.

 

I've looked up articles trying to show practical uses for them, but they seem to go even further above my head than just the word 'lambda'. Rvalue / moving seems confusing just as well; decltype... gah. None of the new stuff makes much of any sense. The only thing I've understood so far is auto, and to a half-way extent: the new for loop style.

 

I've read through a third of C++ Primer 5th, and so far it's not really shed any new light to me. The frustration of these new features and my inability to grasp them has me concerned... How is it some clicked onto the new concepts rather fast? And where can I go to get to that point?



Sponsor:

#2 JTippetts   Moderators   -  Reputation: 9004

Like
17Likes
Like

Posted 18 February 2014 - 10:02 PM

Don't feel too bad, lots of people don't  grok lambdas. The thing is, you might not need the new features, at least not yet. If you don't have a strong idea of what purpose lambdas serve, then you can probably get away with not using them. Lambdas are nice, but it was possible to write perfectly viable C++ code without them for years; that hasn't changed. Just do your best with what you know, and as you gain greater understanding of programming in general other things will open up to you.



#3 Serapth   Crossbones+   -  Reputation: 5907

Like
16Likes
Like

Posted 18 February 2014 - 10:51 PM

Lamdas are scary sounding then they really are.

 

Do you find the expression "anonymous function" easier to grok?  WIthout going into the isoteric details, lambdas are basically anonymous functions.

 

If "anonymous function" is still too confusing, think of a lambda as a function without a name, which makes the syntax suddenly make a lot more sense.

 

[](int val) -> int { body }

 

It's pretty much just like a normal function syntax, with a few twists.  [] replaces the function name, -> denotes a return type.

 

Also you can capture other variables in scope to allow them to be used within the body of a lamdba by putting them inside the [].  Such as:

 

int i = 42;

[i](int addToI) -> int { return i + addToI; }

 

Most of the time you dont actually have to specify the return type, so this could have been expressed as the slightly easier to grok:

[i](int addToI){ return i + addToI; }

 

I will admit, the C++ syntax for them is ugly as hell... but then, the C++ syntax for just about everything is ugly as hell.  That's part of its charm I suppose?

 

 

 

As to why the hell you would need to use them?  Well you dont.  The world gets by perfectly fine without them.  However... there are many situations, especially dealing with generics where they can greatly improve your code.  Think of all those std container objects you create one off functions for... lamdbas get rid of that... it allows you to write more concise code, like say:

std::sort(intArray.begin();intArray.end();[](int a, int b) { return a < b; });

 

Which is a horrid example by the way, as you could have simply expressed that std::sort(intArray.begin();intArray.end());... but the concept still stands.  There are tons of algorithms in the standard libraries that take a function as a parameter and lambdas can greatly aid readability... if you find them more readable that is.

 

Lambdas have a few neat tricks... you can call them as soon as you declare them and you can use them to initialize a variable, like:

 

bool task1 = false;

bool task2 = true;

bool bDone = [](bool task1Done, bool task2Done) { return task1Done && task2Done; }(task1,task2); // () at end immediately executes.

 

 

Mostly though, yeah, they are just inline, unnamed functions.  Just their implementation is confusing as hell.

 

 

For the record, C# do lamdbas sooooo much cleaner...

 

(values) => action

 

var numbersLessThan10 = numbers.TakeWhile( n => n < 10 );

 

In the above example, the lamdba expression "n => n < 10" is called once for every value in the number arrays ( the current value in the array is the value passed in to the lamdba as n ) until the end or a value is higher than 10.  This is using a lambda in a single line method to replace a traditional ( and error prone ) for loop.


Edited by Serapth, 18 February 2014 - 11:11 PM.


#4 dejaime   Crossbones+   -  Reputation: 4119

Like
11Likes
Like

Posted 18 February 2014 - 11:05 PM

Yes, C++11 is introducing some things lots of C++ programmers would rather avoid than use.
 
C++ is strictly typed, but now the compiler is doing some compile-time type matches that retain the strict typing, but by using an indirect approach. This takes the strict typing to compile-time rather than keeping it at code level, but still result on errors and warnings in case uses can't be matched.
Lambda functions (or anonymous functions, if it makes more sense to you) are an unanimity for functional programming languages (as in functional paradigm). In order to make better use of them, a better understanding of functional programming is always helpful.
 
About me, I'm actually pretty enthusiastic about the changes, but won't get started with them just yet, as my projects are all using the previous standards (backwards compatibility adds to that). 
I've never been any good in generic programming...
#include <functional>
#include <iostream>

using std::cout;
using std::endl;
 
int main()
{
	double pi = 3.14159;
	
	//std::function<double(double)> means that it is a function
	// that takes a double and returns a double.
	std::function<double(double)> truncate = [](double d) {
		return (double)((int)d);
	};
	
	//auto here makes so the above typing is automatically detected.
	auto truncate_auto = [] (double d) {
		return (double)((int)d);
	};
	
	//This here will automatically detect void(void) type.
	auto printpi = [&pi] {
		cout<<pi<<endl;
	};
	
        //Same as printpi, but this one captures a function variable.
	auto void_typed_function = [&printpi] {
		cout<<"call printpi: ";
		printpi();
	};
	
	cout<<"Manually typed truncate: "<<truncate(pi)<<endl;
	cout<<"Automatically typed truncate: "<<truncate_auto(pi)<<endl;
	void_typed_function();
	
	return 0;
}
//Output/////////////////////////////////
//	Manually typed truncate: 3
//	Automatically typed truncate: 3
//	call printpi: 3.14159
/////////////////////////////////////////

Edited by dejaime, 18 February 2014 - 11:17 PM.


#5 frob   Moderators   -  Reputation: 25435

Like
11Likes
Like

Posted 18 February 2014 - 11:22 PM

C++ is a living language. It has changed several times in the past. C++14 and C++17 are both on track, so you might want to read what is coming up in C++14.

The biggest C++11 changes, at least the ones that immediately interfered with my work, were these:
* 64 bit integers are now included in type rules
* Enum values are more formalized. Before they were magical constants that were usually typeless replacements of symbols with value, suddenly they have types and that can cause weird behavior
* Some new shortcuts were added to the language. Things like auto types, lambda functions, and range-based loops are a little weird the first time you encounter them but they make sense quick enough.

All the bits of functionality had been growing for years. Most of the new functions and features were available through Boost and compiler extensions that everybody supported. Professional have been using them for years working out the kinks.

For me the biggest change was the 64-bit and enum rules. When working with established code bases that span many programs, many compilers, many operating systems, those rules broke a lot code. Suddenly what was treated as a 32-bit unsigned value became a signed 64-bit value. When decades-old libraries rely on things like -1==SomeEnumValue0xffffffff, the new code will happily compile without warning on C++11 but run with disastrous results.

Don't trouble yourself too much about the other additions. New options for threading and new algorithmic functions are nice to have, but just knowing about their existence is enough for most people.

Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#6 Serapth   Crossbones+   -  Reputation: 5907

Like
8Likes
Like

Posted 18 February 2014 - 11:30 PM

C++ is a living language. It has changed several times in the past. C++14 and C++17 are both on track, so you might want to read what is coming up in C++14.

The biggest C++11 changes, at least the ones that immediately interfered with my work, were these:
* 64 bit integers are now included in type rules
* Enum values are more formalized. Before they were magical constants that were usually typeless replacements of symbols with value, suddenly they have types and that can cause weird behavior
* Some new shortcuts were added to the language. Things like auto types, lambda functions, and range-based loops are a little weird the first time you encounter them but they make sense quick enough.

All the bits of functionality had been growing for years. Most of the new functions and features were available through Boost and compiler extensions that everybody supported. Professional have been using them for years working out the kinks.

For me the biggest change was the 64-bit and enum rules. When working with established code bases that span many programs, many compilers, many operating systems, those rules broke a lot code. Suddenly what was treated as a 32-bit unsigned value became a signed 64-bit value. When decades-old libraries rely on things like -1==SomeEnumValue0xffffffff, the new code will happily compile without warning on C++11 but run with disastrous results.

Don't trouble yourself too much about the other additions. New options for threading and new algorithmic functions are nice to have, but just knowing about their existence is enough for most people.

 

 

I would say functionally ( pun not intended ), for a new developer that isn't supporting an existing code base, auto is probably the single biggest new feature.

 

Unless of course we ignore TR1, in which case smart pointers, then auto.

 

auto however was desperately needed to help developers write somewhat human readable templated code.



#7 Servant of the Lord   Crossbones+   -  Reputation: 22704

Like
24Likes
Like

Posted 18 February 2014 - 11:33 PM

You originally learned C++ piece-by-piece over time, so don't worry about not understanding C++11 all at once. smile.png 

C++11 extends C++ in a few ways, but it doesn't remake the entire language, so all your prior C++ knowledge is still useful and entirely relevant.
 

Lambdas confuse me, in both their syntax and their purpose.


(You should know about function-pointers and callbacks before you learn lambdas)

Lambdas are functions. Lambdas are functions. Lambdas are functions.
(Okay, that's a lie. But it's one of those lies that make learning a subject easier to understand)

This is a normal function:
void MyFunction(int x) { x = 5; }
This is an unnamed lambda function:
[](int x) { x = 5; }
Ignore the "[]" for a moment. That is the symbol used to begin a lambda, but it serves another purpose as well.

Let's compare the two side-by-side:
void MyFunction(int x) { x = 5; }
             [](int x) { x = 5; }
One's a function named 'MyFunction'. The other is unnamed.

Cool. By why? Normal functions can only be defined outside of any function. In C++, you can't define a function inside a function.
int main()
{
    //----------------
    //INVALID:
    int foo()
    {
       return 0;
    }
    //----------------

    int x = foo();
}
Lambdas can only be defined and used inside functions:
int main()
{
    auto foo = []()
    {
       return 0;
    }

    int x = foo();
}
That declares an unnamed function that returns 0. Then 'foo' becomes, because of 'auto', a function-pointer or function-reference to the unnamed function.

But imagine I wanted to use a local variable of 'main()' in my lambda...
int main()
{
    int localVar = 357;
    
    auto foo = []()
    {
       return localVar;
    }

    int x = foo();
}
...lambdas can "capture" the local variable, either by value or by reference, and access it later (assuming the reference is still valid).

This is why lambdas technically aren't functions: they are actually functors - which are normal C++ classes that behave like functions but can have member variables and other stuff. Functors is the name programmers give to the idea of classes that behave like functions. Though not a built-in feature of C++, C++ is flexible enough to allow it, and functors have always been in C++ (functors are just classes).

So a lambda is, behind the scenes, an unnamed class that pretends to be a function. Classes can pretend to be a function by overloading the operator '()', to be used like myClass(), and can accept parameters.

There's a new feature in C++11 for regular functions. Instead of specifying a normal C++ function like this:
int MyFunc() { return 0; }
You can optionally define it like this:
auto MyFunc() -> int { return 0; }
A bit weirder, but useful with templates in some cases.

Anyway, you use the same syntax if you want to specify the return type of a lambda:
[]() -> int { return 0; }
Now, I mentioned that lambdas can "capture", either by value or by reference, local variables.
You can specify how you want to capture them, by using the [] part of the lambda and inserting a = (for capture-by-value) or an & (for capture-by-reference).

You can also specify each variable that it captures manually, and decide whether they are caught by reference or value individually.
 

Rvalue / moving seems confusing just as well;

That's the thing that'll trip up most people coming to C++11, I think. Luckily, it's something that can be entirely ignored without any harm until you are ready to learn it.

I think the hardest part of learning move-semantics is that it's not explained very well. Once you understand it, you can shrug and say to yourself, "Hey, that isn't half as complex as I thought". And it doesn't require some weird twist of thought either, just a halfway decent explanation without scary terminology.

Imagine you had a class that holds alot of data by pointer:
class MyClass
{
   HugeData *lotsOfData;
};
If you did this:
MyClass myClassA;
MyClass myClassB = myClassA;
The default copy-constructor of C++ would have only a bit-level copy of MyClass be made.
That means, the pointer would get copied, but not the data it points to.

'myClassB' and 'myClassA' would both point at the same data!

This means, if you have myClassA modify the data, myClassB's data (the same data) would get modified too. That'd be a bug in your code.
And when myClassA goes out of scope and destructs, it'd free the data, and the next time myClassB tries to access it, your program would crash.

Thankfully, C++ lets us specify our own copy functions. There's the copy-constructor function and the copy-assignment function.
Now, we can tell MyClass that when it is copied, it ought to manually copy the actual data and not just the pointers.

But copying is expensive. What if we were doing this:
MyClass myClassA = ...lots of data...;
MyClass myClassB = myClassA;

return myClassB;
We'd be needlessly copying a huge amount of data, because we never modify or use myClassA again. In this kind of circumstance, we'd actually prefer that myClassA just hands myClassB the pointer instead of copying the data, and that myClassA should know not to bother freeing the data, and let myClassB own and free the data on its own. We'd rather, in some circumstances, transfer mental "ownership" of the data and just copy a tiny pointer instead of copying a huge block of data. We call this "moving" instead of "copying".

So C++11 added a way to give classes custom move functions. Just as there are "copy constructors" and "copy assignment operators", C++11 added "move constructors" and "move assignment operators".

And that's it. So when we do this:
myClassB = myClassA;
Data is copied. The class's copy functions get called.

And when we do this:
myClassB = std::move(myClassA);
Data is moved. The class's move functions get called.

When a move function gets called, and myClassA moves its data to myClassB, it gives up its right to that data, so you shouldn't try to use myClassA anymore, because it doesn't have any right to that data and might not be able to access it. But you can assign something else to myClassA before continuing to use it.
 
There's more details, like when and where C++ moves data instead of copies it, but the above is the big picture "why" and "how". Move semantics gives official standardized support for an idea that already existed - transferring ownership of data when a copy isn't needed.

decltype... gah.

If you understand 'auto', 'decltype' is pretty similar.
 
int x = 5;
auto y = x; //'y' is an int

int x = 0;
decltype(x) y = 0; //'y' is an int
decltype(x) provides a way to say, "the type that is 'x'".
decltype doesn't actually use 'x', it just (at compile-time) checks what type 'x' happens to be.

Unlike 'auto' decltype doesn't have to create a variable - it can be used for things like typedefs:

typedef int MyTypeA; //Makes 'MyTypeA' another name for 'int'.

int x = 0;
typedef decltype(x) MyType; //Makes 'MyTypeB' another name for int, because decltype(x) means 'int' since 'x' is int.
MyTypeB y; //Uses the typedef 'MyTypeB', which is an int.
You wouldn't be able to do that with 'auto', because the compiler wouldn't know what type 'auto' was supposed to be:
typedef auto MyType; //Won't compile, because what type is 'MyType' here?
It is mostly used in templates, where you don't actually know the type of stuff until compile-time.
 

The only thing I've understood so far is auto, and to a half-way extent: the new for loop style.


I like the new for loop (called 'range-based for loop' when you want to get technical, or 'range-for' for short).

Given a container like std::vector, range-for will iterate over the entire container.
for(int x : vectorOfInts) //Iterate, copying each element into 'x'.
for(int &x : vectorOfInts) //Iterate, making 'x' reference each element.
for(const auto &x : vectorOfWhoKnowsWhat) //Iterate, making 'x' be a const-reference to each element.
It's a shorthand way of writing:
for(std::vector<int>::iterator it = std::begin(vectorOfInts); it != vectorOfInts); ++it)
{
   int &x = *it;
}
...which isn't very pleasing to look at. laugh.png 
 

How is it some clicked onto the new concepts rather fast?

The same way you are. I started in late 2010 or early 2011 (C++11 was finished in late 2011, so I started before it was standardized).
Some people have been following C++11 for years and years - bits and pieces of C++11 have been studied and talked about since 2003, though its changed alot.

Also, if you are only just now getting a grasp of regular C++'s features, alot of C++11 is easier to understand if you know advanced C++ features and mindsets - which you pick up overtime.
 

And where can I go to get to that point?

Bit by bit, piece by piece, through use, through reading forum threads and asking questions and reading articles.

These videos helped me alot. I spent a good week watching the first Going Native's videos, and then invested a week watching the second Going Native.

Some of it went right over my head... but hey, when originally learning C++, alot of normal C++ went over my head the first time I encountered certain features. But after encountering a feature multiple times (like templates in C++98, or like move-semantics in C++11), is starts to sink in, bit by bit.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#8 HScottH   Members   -  Reputation: 516

Like
4Likes
Like

Posted 18 February 2014 - 11:58 PM

I have been programming C since long before C++, and C++ since it's birth.  The standard has evolved a lot, and it's just trying to keep up with the innovation happening elsewhere, in other langauges.

 

Honestly, lambda's are simpler to manage than function pointer declarations.  As with most things, it's simple, it just won't seem that way until it does for you.

 

I don't like some of the additions; things like auto and decltype are not expanding the capability of the language, but only helping some become more comfortable with it.  I fully expect a day where two expert C++ coders can write code that the other cannot understand :-)



#9 dejaime   Crossbones+   -  Reputation: 4119

Like
2Likes
Like

Posted 19 February 2014 - 12:05 AM

I don't like some of the additions; things like auto and decltype are not expanding the capability of the language, but only helping some become more comfortable with it.

Even though I agree that these are not adding up to the language, comfort plays a really important role when learning a language. I lost account of how many times I've seen people asking for help when their problem was simply misusing and 'misdeclaring' iterators... This kind of problem adds a lot to the learning curve and features like auto will help anyone who is just starting.



#10 frob   Moderators   -  Reputation: 25435

Like
11Likes
Like

Posted 19 February 2014 - 12:34 AM

I don't like some of the additions; things like auto and decltype are not expanding the capability of the language, but only helping some become more comfortable with it.  I fully expect a day where two expert C++ coders can write code that the other cannot understand :-)

We are WAY beyond the scope of For Beginners at this point, so I'm half tempted to end it or move it to general programming, but I'm also interested to just watch and see where it goes...

Both auto and decltype are necessary for more than just ease of use.

Auto is absolutely a shorthand in many cases, that is why it was proposed, but then people discovered it had a useful side effect. One of the big fighting points over lambdas was how to manage their type. For example, what is the type of this lambda: [](int i)->int{ return 0; } It is a surprisingly hard question. I think (but honestly am not certain) the type is the typecasted result of a member function, the arrow operator, of an unnamed inline structure. It has no name; you can't make a variable to hold it because you can't express its type. During compilation the compiler generates a formulaic name for it before it gets inlined, but it isn't something you as the programmer can write. For many lambdas you can assign the member function to a function pointer but then you lose the inline benefits. The odd thing was that type deduction --- which had been suggested for shorthand --- also allowed the compiler to figure out the unnamed inline structure, which in turn means you get both the benefits and issues of inline functions. So even if the type is unspeakable (it has no name the code can use) type deduction allows the unspeakable name to be used.

The decltype addition is really only useful in templates. You can basically say "this template requires three types, I'm going to do (a*b+c) and return the result. Figure out what type the result is and use that as a template signature." There is no real equivalent. There is no way for the template writer to know what classes it will be; maybe int, maybe float, maybe complex, maybe some custom code type. The auto keyword doesn't apply because the type cannot be deduced that same way. The template type is something the compiler can figure out, but it requires information only the compiler knows.

Finally, I'd argue we were already at the point where two experienced c++ programmers can write code they cannot read. I've written c++ code that I couldn't read days later, just continued using it while praying it had no bugs. There are template monstrosities that could win awards at obfuscated code contests. The auto keyword change helps fix that; the decltype introduction makes it worse.


Check out my book, Game Development with Unity, aimed at beginners who want to build fun games fast.

Also check out my personal website at bryanwagstaff.com, where I write about assorted stuff.


#11 Servant of the Lord   Crossbones+   -  Reputation: 22704

Like
3Likes
Like

Posted 19 February 2014 - 12:35 AM

I don't like some of the additions; things like auto and decltype are not expanding the capability of the language, but only helping some become more comfortable with it.  I fully expect a day where two expert C++ coders can write code that the other cannot understand :-)

auto is required to hold and use local lambdas, if the lambda has captures (Only non-capturing lambdas can be accessed as function-pointers, because only non-capturing lambdas are actually functions).

decltype() is used to implement auto, as well as to handle certain template situations where you have to jump through too many hoops to describe a type or where you are incapable of describing a type.

Range-based for loops are shorthand and only shorthand, and don't enable any new feature - so your ire should be directed in that direction... that is, if range-based for loops didn't enable behind-the-scenes optimizations that compilers can take advantage of. wink.png

 

[edit:] Ninja'd ph34r.png


Edited by Servant of the Lord, 19 February 2014 - 12:37 AM.

It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]


#12 HScottH   Members   -  Reputation: 516

Like
7Likes
Like

Posted 19 February 2014 - 02:03 AM

Points well taken, oh higher-than-my-reputation-people!

 

My mental model when programming is as though C++ is an OOP C, a higher-level abstraction for what I understand the CPU to be doing (from years of ASM work).  Nonetheless, I love the STL and other abstractions, and in 11, lambda's and especially cross-platform threading!  I suppose there will just be features I am unlikely to use--well, you know, until I absolutely need them--because I can solve all the problems I know using older mechanisms.

 

A much more mature and capable language now, C++, as a descendant of C, still makes me want to hear Kernighan's wise words: "C is not a big language, and it is not served well by a big book."

(Stroustrup made no such promises, but once upon a time, even C++ was not a big language...)



#13 Aardvajk   Crossbones+   -  Reputation: 7701

Like
2Likes
Like

Posted 19 February 2014 - 02:20 AM

I'm curious about this that dejaime posted:

 

std::function<double(double)> truncate

 

That syntax in between the <>'s, is that some kind of new language extension? Not heard anything about this but doesn't seem to be something that would have been valid in pre C++-11.



#14 BitMaster   Crossbones+   -  Reputation: 4921

Like
2Likes
Like

Posted 19 February 2014 - 02:26 AM

Maybe my coffee hasn't kicked in yet but that looks to me like the function syntax I have been using for years (starting with boost::function, nowadays std::function). It's simply std::function<ReturnType (ParameterType1, ParameterType2, ...)>.

Edit: Boost used to warn that while it's the preferred syntax not all compilers support it. But all the MSVCs I have used it with never complained.

Edited by BitMaster, 19 February 2014 - 02:27 AM.


#15 Ryan_001   Prime Members   -  Reputation: 1569

Like
2Likes
Like

Posted 19 February 2014 - 02:33 AM

I'm not a big fan of the way rvalue and perfect forwarding interact.  Perfect forwarding should have had a separate syntax, and not be tacked onto rvalues with unintuitive reference collapsing rules and special template deductions.  I understand the need for perfect forwarding, but it has nothing to do with rvalues... why reuse the syntax??  C++ template deduction rules are already convoluted enough as it is.  They needed to make it simpler, not more complex.



#16 cdoubleplusgood   Members   -  Reputation: 851

Like
6Likes
Like

Posted 19 February 2014 - 04:28 AM

But imagine I wanted to use a local variable of 'main()' in my lambda...

int main()
{
    int localVar = 357;
    
    auto foo = []()
    {
       return localVar;
    }

    int x = foo();
}
...lambdas can "capture" the local variable, either by value or by reference, and access it later (assuming the reference is still valid).

 

 Two errors here:
1. Missing default capture mode, must specify either [&] or [=];
2. Missing ; behind lambda definition:

int main()
{
    int localVar = 357;
    
    auto foo = [=]()
    {
       return localVar;
    };

    int x = foo();
}

Edited by cdoubleplusgood, 19 February 2014 - 04:29 AM.


#17 phantom   Moderators   -  Reputation: 8081

Like
6Likes
Like

Posted 19 February 2014 - 04:42 AM

I'm curious about this that dejaime posted:
 
std::function<double(double)> truncate
 
That syntax in between the <>'s, is that some kind of new language extension? Not heard anything about this but doesn't seem to be something that would have been valid in pre C++-11.


It's just function type declaration minus the typename part;
typedef double (*fp_t)(double)
fp_t foo;

typedef std::function<double(double)> fp_t;
fp_t foo;
boost::function used this syntax before std::function was folded into the standard.

Edited by phantom, 19 February 2014 - 04:42 AM.


#18 NightCreature83   Crossbones+   -  Reputation: 3286

Like
3Likes
Like

Posted 19 February 2014 - 05:00 AM

Pretty comfortable with my c++ code now; I get classes, I get using templates and STL, smart pointers, and to an extent, exceptions. What I don't get is most of the new 2011 standard. Lambdas confuse me, in both their syntax and their purpose.

 

I've looked up articles trying to show practical uses for them, but they seem to go even further above my head than just the word 'lambda'. Rvalue / moving seems confusing just as well; decltype... gah. None of the new stuff makes much of any sense. The only thing I've understood so far is auto, and to a half-way extent: the new for loop style.

 

I've read through a third of C++ Primer 5th, and so far it's not really shed any new light to me. The frustration of these new features and my inability to grasp them has me concerned... How is it some clicked onto the new concepts rather fast? And where can I go to get to that point?

Other people grokked them fast because lambdas aren't new other languages already had these, lambdas in C# for example, they started as nameless delegates. I see lambdas as a delegate/callback function that you specify in the same line as where you pass them to a function that needs a callback. The lambdas in C++11 have a more function approach and I find them easier to read then their C# counterparts, its the capture that is hard.

 

A good use for a lambda is when you want to extend a std::find or std::find_if or std::sort, instead of passing it a functor or callback, you pass it a lambda that specifies what you want the predicate for the function to be. This keeps the code for the predicate and call of that predicate closer together than the functor or callback options.

 

RValue/Move semantics is something that was sorely missed and you had to program around this like reserving the size of your vector if you knew how big it was going to be to avoid an array copy. Move semantics will allow you to care a little less about copy performance if implemented correctly.

 

Decltype is a way in which we can access the type of an expression, this is useful in meta template programming and generic programming where you had to hack around these things before.

 

auto and the new intialiser lists are the most useful features added in C++11 because it allows you to write your code in an easier fashion and avoid a parsing problem.

class Foo
{
};
 
void Bar()
{
    Foo foo(); //The compiler sees this as a function prototype not the instantiation of an instance of Foo
    Foo foo {}; //This is now always seen as creating and instance of Foo
}

Edited by NightCreature83, 19 February 2014 - 05:00 AM.

Worked on titles: CMR:DiRT2, DiRT 3, DiRT: Showdown, GRID 2, Mad Max

#19 doyleman77   Members   -  Reputation: 366

Like
7Likes
Like

Posted 19 February 2014 - 07:08 AM

I thank everyone who had explanations on all topics. I tried a few sample lambdas to try to get a feel; and it's beginning to make sense. I'll be honest in that I never really used a callback; let alone know what one is. From my understanding, it's passing a function into another, and having it perform at a later point within that first function.

Move constructors and assignments are entirely cleared up; that actually seems like a brilliant move; and left me wondering why that wasn't part of the standard earlier.

 

decltype has also been cleared up; and I can see the uses for that definitely. I bookmarked the GoingNative page; and will check that out later today when I finish classes; thanks for the link!

 

I really do appreciate all of your guy's explanation, and time taken to give them. The depth of some of them were quite long, but served to help more than what the book had shown; so thanks to all on their contributions!



#20 Servant of the Lord   Crossbones+   -  Reputation: 22704

Like
1Likes
Like

Posted 19 February 2014 - 04:31 PM

Two errors here:
1. Missing default capture mode, must specify either [&] or [=];
2. Missing ; behind lambda definition


Thanks, I usually forget the semicolons. laugh.png


It's perfectly fine to abbreviate my username to 'Servant' rather than copy+pasting it all the time.
All glory be to the Man at the right hand... On David's throne the King will reign, and the Government will rest upon His shoulders. All the earth will see the salvation of God.
Of Stranger Flames - [indie turn-based rpg set in a para-historical French colony] | Indie RPG development journal

[Fly with me on Twitter] [Google+] [My broken website]

[Need web hosting? I personally like A Small Orange]





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS