Entries:
Comments:
Posts:

Loading User Information from Channel 9

Something went wrong getting user information from Channel 9

Latest Achievement:

Loading User Information from MSDN

Something went wrong getting user information from MSDN

Visual Studio Achievements

Latest Achievement:

Loading Visual Studio Achievements

Something went wrong getting the Visual Studio Achievements

Stephan T. Lavavej - Core C++, 9 of n

Download

Right click “Save as…”

In part 9, STL digs into lambdas and other expressions. Lambdas are very useful and you've know doubt been enjoying them in your modern C++ programming. As you can imagine, STL will go deep and teach you things about lambdas that you may not know. You'll also learn a lot about order of precedence and associativity for expressions in only the way Stephan can teach you (thorough treatment). Tune in.

See part 1: Name Lookup
See part 2: Template Argument Deduction
See part 3: Overload Resolution
See part 4: Virtual Functions
See part 5: Explicit and Partial Specialization
See part 6: New C++11 features added to the Visual C++ 2012 compiler (CTP)
See part 7: Usual Arithmetic Conversions and Template Metaprogramming
See part 8: do-while loop, casts, one definition rule

Tags:

Follow the Discussion

  • So glad it's back! Smiley

  • felix9felix9 the cat that walked by itself

    Smiley NICE

  • Very pleased to see Stephen again, I imagine he's been busy with Visual C++ 2013 ahead of the BUILD conference, so i guess we can forgive him for disappearing from the C9 radar screens for a while Wink

  • Kostas DritsasKostas Dritsas

    I believe lamdas are explained very well here and, to some extend, in depth. Some hard things -to unexperienced programers, not
    acquainted with lamdas- are easy if explained well! Well done!

  • Glad you are back ! Great one as always. Smiley 

  • IvanIvan

    Welcome back STL... cant wait to watch this...

  • STLSTL

    Tom: Yep, I was super busy getting the STL ready for VS 2013 Preview. I've got a VCBlog draft with a detailed changelog that I'll be able to publish after the Build conference.

  • Welcome back! We missed your talks!

     

  • Great to see you back in action....

  • @STL:Can't wait to read your blog update post BUILD Stephan. I usualy diff the sources, but having to insights will help upgrade confidence considerably.

    Just wanted to say I totally respect the work that engineers like James McNellis and yourself do for the Visual C++ team Stephan, and I imagine this decision was probably made higher up - but is there any chance of retro-fitting the C++ 11 stuff from Visual Studio 2013 back to VisualStudio 2012? You folks kindly u-turned on Windows XP and I was wondering if once some of the VS2013 testing pressure was off you could 'finish the job' in VS2012? I had hoped that VS2013 would look forward to C++ 14, rather than back to pick up the pieces of '11 (which should IMO have been addressed in '12.)

    I do not mean to sound ungrateful here, I love Visual C++, it's practically been my desktop for the past 20 years, but getting new compilers installed - particularly for enterprise ISVs where multiple products and teams are at work on a shared code base is difficult and swallowing a VS2012 Update 4 (?) would be less painful than having to jump to VS2013 - which of course we will do in time, but I feel shouldn't have to do in order to pick up the bits that where promised for '12 (more than 7 months ago now...)

  • cmeerwcmeerw

    Just wanted to comment on the return type deduction with multiple return statements. My understanding is that the semantics of what VS implements are slightly different to what C++14 will support. I guess VS2012 implements something similar to what was originally proposed in Core Issue 975, but for C++14 the semantics are different and described in N3638, although there is some overlap.

  • Finally some more, thank you for doing this. Great bed time stories.  Smiley

    One thing though: At 51:15 you say that your ++n lambda is “totally allowed by the STL”. I would disagree after reading the box here because you're causing side effects. And in a parallel transform version I would expect n to be indeterministically changed.

    It also says “until C++11”, but how would C++11 cope with this?

  • Thanks for another great episode Stephan. I really enjoy watching these.

    One thing that eludes me is the purpose of the pointer-to-member operators. They're easy enough to use by why bother since I can just reference the member directly from the object itself. Is this something that simplifies template programming?

  • Vipul S. ChawatheVSChawathe Vipul

    long awaited delight. Smiley

    At some length documentation starts feeling dry to me. When I get examples to lay hands-on, then its more comfortable for me to look into documentation over and over.

    I prefer your presentations as the examples are cleanly related with the topic, and when consuming the topic for making app solution for some particular domain (say games) then I'm free to innovate than be induced by another software architect's choices- that's bad as too many chefs spoil the broth. Every choice is like sequence point following which I collect peer reviews of choices, whose responsibility is with me.

    So awaiting your presentations is definitely worth the wait..

  • STL meowSTL meow

    (This is STL, really - something weird happened where I can't view this page logged in under my account, even though I was able to when I posted my first comment here. I can view Part 8, just not this one. If anyone doesn't believe it's me, mail me - my address is easy to find, it's in the STL11: Magic && Secrets slides.)

    Tom> is there any chance of retro-fitting the C++ 11 stuff from Visual Studio 2013 back to VisualStudio 2012?

    This will be addressed in my VCBlog post. In fact, my draft has an FAQ at the end, where this is question #3.

    (I'm not allowed to talk about 2013's features yet - while I could *probably* get away with answering this question now, I prefer to avoid annoying my bosses and boss-like entities.)

    cmeerw> Just wanted to comment on the return type deduction with multiple return statements. My understanding is that the semantics of what VS implements are slightly different to what C++14 will support.

    The rules appear to be exactly the same to me (although I'm not a Core Language guru, I just play one on TV).

    VC doesn't support this in normal functions, and (except for trailing return types) it doesn't support auto or decltype(auto) return types, and it doesn't support the recursion rules (because lambdas can't be recursive). But as far as multiple return statements are concerned, I believe we follow the "all the types have to be the same" rules.

    primfaktor> At 51:15 you say that your ++n lambda is "totally allowed by the STL". I would disagree after reading the box here because you're causing side effects.

    N3690 25.3.4 [alg.transform]/2 prohibits transform's functor from invalidating iterators to the elements being traversed, and prohibits modifying elements in the sources/destination, but other side effects are invisible as far as the STL is concerned. (transform() specifically does not guarantee that the elements will be transformed in order. It was probably a bad idea for me to demonstrate concatenating to_string(n) with transform().)

    Similarly, 25.1 [algorithms.general]/8-9 prohibits Predicates and BinaryPredicates from modifying their arguments, but they can modify other state (subject to the restriction that in certain contexts, like sort(), they must return consistent answers over time; you can't say that X is less than Y at one point, then later that it's not-less-than Y).

    > And in a parallel transform version I would expect n to be indeterministically changed.

    The STL is forbidden from performing autoparallelization except when it's unobservable. For example, count(const int *, const int *, const int&) could be autoparallelized unobservably, but invoking a user-defined functor is observable. This is 17.6.5.9 [res.on.data.races]/8: "Unless otherwise specified, C++ standard library functions shall perform all operations solely within the current thread if those operations have effects that are visible (1.10) to users."

    > It also says "until C++11", but how would C++11 cope with this?

    Sorry, what are you referring to?

    geeyef> One thing that eludes me is the purpose of the pointer-to-member operators. They're easy enough to use by why bother since I can just reference the member directly from the object itself. Is this something that simplifies template programming?

    Pointers to members are especially useful when you have a container of objects and want to select a particular member function or data member from each of them and have an STL algorithm do something with it. If you're writing a loop yourself, you can just access the member directly, but with an STL algorithm you need a way to say "please select this member".

    Here's a full example:

    C:\Temp>type meow.cpp
    #include <algorithm>
    #include <functional>
    #include <iostream>
    #include <string>
    #include <vector>
    using namespace std;

    class NPC {
    public:
    NPC(const string& name, const int hp)
    : m_name(name), m_hp(hp) { }

    friend ostream& operator<<(ostream& os, const NPC& npc) {
    return os << "(" << npc.m_name << ", " << npc.m_hp << ")";
    }

    void damage(const int n) {
    m_hp -= n;
    }

    bool dead() const {
    return m_hp <= 0;
    }

    private:
    string m_name;
    int m_hp;
    };

    template <typename C> void print(const C& c) {
    for (const auto& e : c) {
    cout << e << " ";
    }

    cout << endl;
    }

    int main() {
    vector<NPC> v;
    v.emplace_back("Walton Simons", 100);
    v.emplace_back("Joseph Manderley", 10);
    v.emplace_back("Bob Page", 500);
    v.emplace_back("Paul Denton", 50);

    print(v);

    v[0].damage(100);
    v[2].damage(1729);
    v[3].damage(47);

    v.erase(remove_if(v.begin(), v.end(), mem_fn(&NPC::dead)), v.end());

    print(v);
    }

    C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp
    meow.cpp

    C:\Temp>meow
    (Walton Simons, 100) (Joseph Manderley, 10) (Bob Page, 500) (Paul Denton, 50)
    (Joseph Manderley, 10) (Paul Denton, 3)

    VSChawathe: Thanks!

  • JohnJohn

    STL, I have question not related to this session. Maybe you would like to not pollute this post with a random question like that. Could I ask your opinion via e-mail then?

    My question is about 'using namespace std;' vs 'std::_name_'. I am well aware of the StackOverflow discussions where the majority of programmers think std::_name_ is the way to go and pulling the whole namespace into the global one is bad. However in my company my team leader praises omitting std:: for cleaner visuals. I am still not used to it, I just want to write std::. Not just to write it, but to avoid name conflicts.

    How would you comment on this? What do you prefer?

  • Vipul S. ChawatheVSChawathe Vipul

    @meow I've 2 profiles on Microsoft sites as well and strangely using my live account makes me use the new one.. I've to discard http://social.msdn.microsoft.com/profile/vipul%20s.%20chawathe/ for http://social.msdn.microsoft.com/profile/vipul%20snehadeep%20chawathe/ So much for provenance. If you find related way by inside-out approach, submit my example to get both my profiles merged. Thnx. Smiley Bow Wow (& that's doggie barks).

  • Hi Stephan, you mention that the original motivation for lambdas in C++ was when working with the Standard Library (that is as inputs to higher order functions), but I find them an incredibly useful tool to avoid code duplication *within* a function, often in a way that better preserves function level encapsulation (better that is than say a module level function the the anonymous namespace). A classic example of this occurs when writing exception catch handler logic. Do you consider this an 'abuse' of lambdas? When do you use them outside of higher-order functions like those found in <algorithms> ?

  • Thank you. That's makes complete sense now. I've been indirectly using it the whole time via the STL I didn't realize it. Never really had to write my own generic algorithms or containers since the STL pretty much has everything I need.

  • STL MSFTSTL MSFT

    (I'm still unable to view this page while logged in, but I guess I can say MSFT instead of meow for uniqueness.)

    John> My question is about 'using namespace std;' vs 'std::_name_'.

    (Terminology note: "using namespace std;" is a using-directive, while "using std::tuple;" is a using-declaration.)

    The only absolute rule here is that using-directives and using-declarations should never appear at global scope in headers, because that'll affect any source files including that header (and any other headers included afterwards) whether they want it or not. (Within headers, you should think carefully before putting using-directives and using-declarations at namespace scope, because users might want to say "using namespace YourNamespace;" and they might not want that to drag in stuff from other namespaces. Note that block scope within headers is totally isolated.)

    Aside from that, it's mostly a matter of personal preference. Relying on using-directives means that your code might fail to compile in the future, if new names are added to any of those namespaces (or even if your TU ends up dragging in headers it wasn't dragging in before). I've dealt with this problem in my code at home, where I relied on "using namespace std; using namespace boost;" and Boost ended up being a victim of its own success when shared_ptr appeared in std. And as you know, explicitly qualifying everything is verbose.

    I'm leaning towards using-declarations myself; they're more verbose than using-directives, but less than qualifying everything everywhere, and they aren't vulnerable to new stuff appearing in namespaces because they're so targeted.

    Tom> A classic example of this occurs when writing exception catch handler logic.

    Well, you shouldn't be writing too many of those. (At home, I've recently started using Boost.ScopeExit now that it's powered by lambdas - which I believe happened after I filmed an STL video demonstrating ScopeExit - because it's a terse alternative to writing one-time-use RAII classes for old-style APIs. I'd rather write a wrapper class for anything used repeatedly, though.)

    > Do you consider this an 'abuse' of lambdas? When do you use them outside of higher-order functions like those found in <algorithms> ?

    I wouldn't say that using lambdas outside of their traditional habitats (customizing STL algorithms, initializing std::functions/threading stuff, converting to function pointers for C-style callback APIs, etc.) is abusive, but there are definitely limits when named functions or function objects should be preferred. If your lambdas start to get really big, you should consider making them named functions/functors. (JonCaves once told me about finding a multi-hundred-line lambda in a codebase that I won't name.) If you need recursion, absolutely give it a name, don't attempt crazy hacks (I have seen people do unspeakable things).

    One cute use is for complicated initialization of something that can be const afterwards - writing a lambda and immediately invoking it is one way to achieve this. Fortunately, C++11 initializer lists are a better way to initialize containers, so that replaces some uses.

    By the way, <algorithm> doesn't contain any higher-order functions. bind() is a higher-order function (it consumes and emits functors). sort() is just a sort whose behavior you can control via an ordinary functor - it doesn't emit functors.

  • STLSTL

    Yay, the C9 team fixed my profile (there was a "duplicate record" in the database).

  • Truly outstanding presentation, clear, concise, precise, to the point.

    Can you please please post the excel file with operators order, it'll make for a nice bookmark?

     

  • STLSTL

    I uploaded it to my SkyDrive: http://sdrv.ms/1c1zv0b

  • IvanIvan

    @STL
    one small offtopic Q related to STL:
    AFAIK all STL containers in VS11 are optimally small considering their current representation. Does this cover string? From what I know it could be as big as vector, but it is bigger. I guess it is so that SSO kicks in more often. How far from truth am I? :D
    And one trivia/opinion Q:
    what is your personal opinion on extra () changing meaning of decltype? I personally hate it with passion and I think there should be declref for easier readability but most ppl seem to be fine with decltype.

  • I love this lectures!

  • STLSTL

    Ivan> AFAIK all STL containers in VS11 are optimally small considering their current representation. Does this cover string?

    Yes, see http://blogs.msdn.com/b/vcblog/archive/2011/09/12/10209291.aspx . (I'm aware of bloat in bind() and std::function that I need to fix, but those aren't containers.)

    > From what I know it could be as big as vector, but it is bigger. I guess it is so that SSO kicks in more often.

    Yes. We activate the Small String Optimization for 15 chars or 7 wchar_ts.

    > what is your personal opinion on extra () changing meaning of decltype?

    It's there for a good reason. decltype's behavior for arbitrary expressions is exactly right - if your return type is decltype(foo()) because you're returning foo(), you really want the answer to be X for prvalues, X& for lvalues, and X&& for xvalues. But it would be weird if int i = 1729; decltype(i) gave you int&. (It would be especially undesirable if you were returning i from a function.)

  • IvanIvan

    @STL
    tnx for the answers, but decltype beside simple stuff like decltype(i) or decltyping based on vector element type is beyond my ability to comprehend. :) All I was here talking about was that decltype is the only AFAIK example of C++ code where ((something is different from (something)-
    x3 and x4 in this Q:
    http://stackoverflow.com/questions/3097779/decltype-and-parenthesis
    So I wondered if you think that is bad for readability(mental parsing by programmer :)).
    But at least now you have material for another episode ;)
    auto and decltype -IDK why but they kind of fit together for me in same episode- I guess because they both deal with type deduction.

  • IvanIvan

    @STL
    I forgot to ask one more question... again opinion based :)
    Would you like to have ability to give custom comparator to map as a lambda? I know about decltype hackery :P but this is one of those things I just feel are limitations while most ppl say write the damn named function. :)

  • STLSTL

    > decltype is the only AFAIK example of C++ code where ((something is different from (something)

    Yeah, this was extensively debated in the Committee.

    > Would you like to have ability to give custom comparator to map as a lambda?

    You can do that through decltype (which currently doesn't work in VC due to a known STL bug), or by declaring the comparator's type as a function pointer and constructing your map from a stateless lambda. I recommend against that, though (it will be less efficient).

  • IvanIvan

    @STL again tnx
    I didnt know Committee had the same concerns. :)


    I knew about "decltype hackery" how I called it, I just find named function less ugly, so my question is would you like to have ISO C++ support constructing comparator from lambda without decltype... and making sure that types of 2 maps constructed from same lambdas(same == same code ignoring spacing and newline) are same.
    I have personal hate :P for decltype where it doesnt feel right(aka 2.1 in this example http://isocpp.org/blog/2012/12/an-implementation-of-generic-lambdas-request-for-feedback-faisal-vali )
    I REALLY hope current draft dropped that. :)

  • IvanIvan

    @STL
    one more thing I forgot to ask... now you can talk about VS 2013... are clocks are now fixed... Afaik there was a bug with steady clock not being steady. And I didnt find anything about that in your huge huge blog post(BTW congrats on fixing all those bugs)

  • STLSTL

    > would you like to have ISO C++ support constructing comparator from lambda without decltype...

    I don't know what that would mean. A lambda expression constructs an object (of a non-default-constructible type), so you need to provide that object during map construction in addition to either the lambda's actual type (via decltype), a function pointer type (for stateless lambdas), or std::function (with the associated runtime costs).

    At least two restrictions would have to be lifted to accomplish this through the type alone - stateless lambdas would have to be default-constructible and decltype(lambda expression) would have to be permitted, and you'd still have to say decltype to get a type.

    > and making sure that types of 2 maps constructed from same lambdas(same == same code ignoring spacing and newline) are same.

    That is essentially asking compilers to "hash" implementations which is tricky in the way you're asking.

    > I REALLY hope current draft dropped that. Smiley

    I believe that is permitted by N3690 although I haven't kept careful track of all the stuff that Core voted in.

    As always, if you don't like it, don't write it. There's lots of things in C++ I avoid using (e.g. virtual inheritance) even if they don't rise to the level of abominations.

    > are clocks are now fixed... Afaik there was a bug with steady clock not being steady.

    No, sorry. I just didn't have time to fix steady_clock not being steady and high_resolution_clock not being high resolution (I need an uninterrupted week to rip out and rewrite their implementations).

    > (BTW congrats on fixing all those bugs)

    Thanks!

  • IvanIvan

    @STL
    again tnx for the answers... it is really interesting to speak to somebody so skilled. I mean it is you know like Nobel prize winner answering your physics question. :)
    regarding lambdas in maps I was talking more from my perspective(code monkey :P ), you are approaching it more from language side. Im not saying you are wrong to do that but I was wondering what do you think about that addition from usability perspective not from how hard is to do it(aka ISO has infinite power and compiler devs have infinite coffee supply) .
    Aka would you like to say something like
    map<string, double, [](const auto& a, const auto& b) {return a.size() < b.size();}>
    I hope it is clear, if not here is the problem explained:
    http://stackoverflow.com/questions/8736997/using-lambdas-in-maps

    "As always, if you don't like it, don't write it."
    Point is that I would like core language support for something like Boost Lambda magic... those things are more magical than unicorns. :)
    aka
    accumulate(s, s + size, char(), (_1 ^ _2));

    If you ask why not use just boost lambda... I kind of fear that they arent as good when it comes to perf as core lang stuff, but I might be wrong, if you know the definite answer(I care only about runtime perf, not compile time) please share. :)

    regarding clocks... I thought that Win API has all that implemented(aka you are just providing C++11 wrappers for "good" old C functions) so it is trivial to do. :)

  • Buddhika Chaturangamacxfadz Buddhi

    Please feed us more details about C++ 14/17 .

    thank you ,

    Stephan.

  • RicodeRicode

    Thank you for your talk! I would highly appreciate some talk about custom allocators. I found your article about Mallocator but some things have changes since then, for example allocator_traits got added into c++11. I did some research and many people are interested in it (especially game developers using custom allocators for small objects, pool, stack etc) while it's really hard to find some comprehensive info (even in working draft).

Remove this comment

Remove this thread

close

Comments Closed

Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.