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++, 4 of n

Download

Right click “Save as…”

In part 4, Stephan teaches us about Virtual Functions. In parts 1-3, we learned about compile-time constructs. Now, we enter the realm of runtime. STL spends some time discussing inheritance and a bit about access control.

Tune in. Learn.

See part 1: Name Lookup
See part 2: Template Argument Deduction
See part 3: Overload Resolution
See part 5: Explicit and Partial Specialization

Tags:

Follow the Discussion

  • Alex KrycekAlex Krycek

    awesome.
    Thanks for your work.

  • Wow!!

    Thank you for this lecture video.

     

  • Yesterday we got the first C++ && Beyond 2012 and today Stephan. Life is being kind to native developers... long may this state of affairs continue. Thanks as always Stephan for another awesome video.

  • vsbrarvsbrar

    I hope this makes C++ more intuitive and give it a new life. I often hear people saying C++ is dead but after listening to Herb Sutter's argument about the future of C++. C++11 is way to go. Keep up the good work. I hope C++11 have more support for weak memory models.

  • MarekMarek

    What surprised me most about virtual functions is that pure virtual function can have implementation/body (but not at the same place as its declaration(?)/definition(?)): http://ideone.com/RdnGm

    Marek

  • Seems like a long time since the 3rd part. Great show!   Smiley 

  • I would still like to see that "parameter passing best practices" episode Wink But if it's gotta be core C++, how about "sequence points are dead, long live the sequenced-before relationship"?

  • rhalbersmarhalbersma

    Thanks Stephan, for another great lecture.

    Too bad time ran out, because it would have been nice to show that the NVI idiom also applies to static polymorphism using the CRTP pattern with a class template `Base<Derived>`. Here you can explicitly downcast the this-pointer in the `Base` class and access a `Derived` class's private implementation, once again showing that access control is orthogonal to visibility.

  • PhilhippusPhilhippus

    Is there a transcript and/or write-up of the lectures for reference purposes? Failing that how about time tags on the video?
    These mindblowingly valuable lectures require proper indexing.

  • GlassKeyGlassKey

    Great stuff again, thanks. I find I use NVI a lot also although I never realised it had a common name. Usually this is because I want to make sure that a specific piece of code is always called before (or after) that part of the behaviour which is customisable by the derived class implementor. So a trivial example would be if I want to allow derived classes to customize a function, but I also want to ensure that the function's argument values are always logged to a file before calling the 'real' code.

    The only annoying part of this pattern is that you have to come up with a slightly different function name for the virtual function... not a big fan of pre-pending 'do' although the other convention I've seen is *appending* 'Ex' which is also a bit rubbish!

  • STLSTL

    Thanks for watching, everyone. That's what keeps me going!

    vsbrar> I hope C++11 have more support for weak memory models.

    C++11's <atomic>, which we shipped in VC11 RTM, fully supports weak memory models like ARM's. The atomics wisely default to sequential consistency, but if you want relaxed/acquire/release/etc. semantics, they are available.

    Marek> What surprised me most about virtual functions is that pure virtual function can have implementation/body

    Correct. "Pure" means "must be overridden" (if you want to get a concrete class).

    yanshuai> Seems like a long time since the 3rd part.

    There'll be another gap between this and Part 5 - I'll be on vacation for a couple weeks.

    NotFredSafe> I would still like to see that "parameter passing best practices" episode

    That definitely counts as part of the Core Language - the only thing I am avoiding in this series is directly covering the Standard Library.

    I basically do episodes when I feel inspired enough about a topic to talk about it for 45+ minutes in a single take. Now that I'm basically done with "how a function call works", I can turn my attention to other matters.

    > But if it's gotta be core C++, how about "sequence points are dead, long live the sequenced-before relationship"?

    That is exceedingly subtle, and has almost no effect for single-threaded code. I figure that anyone experienced enough to make sense of the topic doesn't need me to explain it to them.

    rhalbersma> Too bad time ran out

    I'll never have enough time to cover every area of a topic (I could probably talk about the integral types for 3 solid hours), so my goal is to cover the basics and sketch out the structure of things so people are prepared to learn more, especially as they encounter issues similar to what I've talked about.

    Philhippus> Is there a transcript and/or write-up of the lectures for reference purposes? Failing that how about time tags on the video?

    Every episode is an undiluted stream of consciousness (mine is filled with cats meowing), but maybe Charles has some resources here.

    GlassKey> The only annoying part of this pattern is that you have to come up with a slightly different function name for the virtual function...

    The Standard conventionally uses a "do_" prefix. If I saw an "Ex" suffix, I would expect that (like in the Windows API) it referred to an extended form of an ordinary function (in C++ this is properly achieved by overloading, but C doesn't have that mechanism).

  • VincentVincent

    The override keyword is a nice solution for the case where I think I override but I don't.
    If I need to change the signature of the function in the base class, I wish I could rely on the compiler to give me an error for all the derived class that are now broken (which it will if override is used everywhere). However, I can't rely on that unless I know the override keyword is used everywhere...
    I wish we had a compiler warning when the override keyword is missing. Something we might get in Visual Studio someday?

  • IvanIvan

    Cool lecture, though vector<shared_ptr<>> made me go :/ - because of the performance of shared_ptr, esp if there are many of them.
    BTW Stephen IDK if you can comment but FB released folly(parts that I want to ask you about are optimizations of STL - does VS does something similar to stuff that folly does).
    To save your time I extracted cool STL features:
    1. (allocator here is malloc() if i get it correctly)"It doesn't take a rocket surgeon to figure out that an allocator- aware std::vector would be a marriage made in heaven: the vector could directly request blocks of "perfect" size from the allocator so there would be virtually no slack in the allocator. Also, the entire growth strategy could be adjusted to work perfectly with allocator's own block growth strategy."
    2. "In order to allow fast relocation without risk, fbvector uses a trait folly::IsRelocatable defined in "folly/Traits.h". By default, folly::IsRelocatable::value conservatively yields false. If you know that your type Widget is in fact relocatable, go right after Widget's definition and write this:

    // at global namespace level
    namespace folly {
    struct IsRelocatable<Widget> : boost::true_type {};
    }
    "
    https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md
    I guess you cant use 2. in STL, but you can use if for MS libs that use STL.

    Regarding the memcyp trick I was wondering... is it possible using TMP to determine if a user class is memcypable(by making it memcpyable if every member is memcpyable, so class X{vector<string> vs; int y; } is memcpyable ).

    Again great lecture, one cool thing would be auto. I know ppl think it is super simple, but actually it isnt.
    also you could reshow your trick question regarding for each and auto from GN conf. :D

  • STLSTL

    Vincent> I wish we had a compiler warning when the override keyword is missing.

    That would warn about the whole world, at least at first.

    Ivan> Cool lecture, though vector<shared_ptr<>> made me go :/ - because of the performance of shared_ptr, esp if there are many of them.

    shared_ptr isn't free, but it isn't horribly inefficient.

    > "an allocator- aware std::vector would be a marriage made in heaven"

    Our std::vector and std::allocator (powered by new/malloc/HeapAlloc) don't conspire together. That could improve performance, but I wouldn't expect it to lead to dramatic gains.

    > is it possible using TMP to determine if a user class is memcypable

    std::is_trivially_copyable does this.

    > class X{vector<string> vs; int y; } is memcpyable

    It is not - vector has a nontrivial copy constructor.

    > Again great lecture, one cool thing would be auto.

    That's a good idea, thanks. I'll think about it.

  • VincentVincent

    > That would warn about the whole world, at least at first

    That would for people who enable the warning, which means it'd be opt-in... I don't see that as a bad thing...

    Those warnings are pretty mechanical to fix: assuming the code is otherwise correct all you have to do is add "override" on the line. It gets you to a state where a class of mistake can't happen:
    - adding a method to a derived class without realizing it already exists as virtual on the base class (so overriding it when it's not intended)
    - adding a virtual method on a base class when one of the derived classes already has a function with the same signature
    - changing the signature of a function on the base class and forgetting to update the derived class (this is what override is designed to fix, but how can I rely on it as the author of the base class if the keyword is optional? I could with a warning...)

  • IvanIvan

    @STL tnx for the answers...
    1)regarding vector and memcopyable ... what I wrote was wrong, I was thinking about swap and move. For example if I now call std::sort on vector whose elements are class X{vector<string> vs; int y; } is
    a) compiler smart enough to figure out that swap can be done by memcpy
    a1) if not can programmer tell him that without manually writing sort function.

    2) regarding auto, if you do it please mention
    const vector<double>& fun();
    auto x = fun;// x is not a const ref

  • Great video, thanks a lot!

    One question about slicing: You suggest forbidding any assignment operator and copy constructor in the polymorphic base class. However, how would you in that situation implement the derived class's copy constructor and assignment operator?

    I was always under the impression that slicing was precisely required to say Base(rhs) and Base::operator=(rhs); in the derived implementations.

  • STLSTL

    Ivan> For example if I now call std::sort on vector whose elements are class X{vector<string> vs; int y; }

    C++11's rvalue references v3 (not implemented in VC11 RTM) will automatically generate move ctors/assigns for X. Then swap() and sort() will automatically take advantage of them.

    KerrekSB> However, how would you in that situation implement the derived class's copy constructor and assignment operator?

    You don't; they remain disabled.

    The solution here is a virtual clone() function, which you can invoke on a Base * and get a properly-cloned Derived.

  • @STL: Thanks for the lecture! // Awesome as always Smiley

    Regarding the NVI -- what are some good examples where we'd prefer "protected" access over "private" (and vice versa)?

    I guess it boils down to choosing between protected-virtuals [23.3] and private-virtuals [23.4] in the C++ FAQ, but unfortunately there's no direct comparison in there:
    http://www.parashift.com/c++-faq-lite/protected-virtuals.html

    Another question -- is NVI the same as or different from the Template Method pattern?

    This source calls TM pattern "more generic" (without specifying what's more generic about it):
    http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Non-Virtual_Interface

    While this one seems to show TM as exactly the same thing:
    http://www.parashift.com/c++-faq-lite/private-virtuals.html

  • FranFran

    Great lecture, thanks Stephan.

  • IvanIvan

    @STL
    :
    "C++11's rvalue references v3 (not implemented in VC11 RTM) will automatically generate move ctors/assigns for X. Then swap() and sort() will automatically take advantage of them.".
    I had a really weird experience playing around with poor mans's v3 RVRs(memcpy) (VC11 RC)and hit really weird problems so I was wondering if you could explain it (for understanding of VS purposes, not to debug my code, like I said I did it for fun):
    http://pastebin.com/0NP1v0XL
    So to recap code comments:
    1. in release mode memcpy specialized swap makes code a LOT faster.
    2. in Debug mode with specialized swap I get runtime errors- if I was forced to guess: Debug runtime machinery doesnt deal ok with memcpy swap implementation. :D
    3. in Debug mode by manually implementing Ctor error goes away. (this is really really weird).
    Ignore the lack of functionality of the code, it is just some random operations in ctor... to make element different from each other and to make debugging easier.
    Disclaimer : I reviewed my code to double check that it isnt some stupid mistake, but still it is possible that is the cause.


  • ChewieChewie

    Awesome lecture, really gave me insight on the way to structure things.

    I would be very interested in further discussion about avoiding inheritance for the sake of it. I see a lot of C++ developers that do "java C++" as I call it, with huge boilerplate classes hierarchies when something much more elegant could be conceived. I find it hard to find C++ resources that don't advocate this "inheritance based programming", and I'd love to hear your best practices about that.

  • gh0st0nridegh0st0nride

    These core c++ video aren't being posted on visual c++ blog now? . I see just 2 videos of this listed there. thanks to google for linking me to this link :)

  • STLSTL

    Matt_PD> Regarding the NVI -- what are some good examples where we'd prefer "protected" access over "private" (and vice versa)?

    You'd want "protected" when you'd want the base class to provide an implementation that derived classes can invoke as a helper. (The base implementation can be marked pure if you want to require derived classes to override it. Of course, if the base implementation is protected, pure, and implemented, a derived class can override it and just call the base implementation.)

    > Another question -- is NVI the same as or different from the Template Method pattern?

    I don't really pay attention to design patterns as I don't find them to be especially useful. I've heard that the NVI is one way to implement the "Template Method" pattern, which sounds right to me.

    Ivan> I had a really weird experience playing around with poor mans's v3 RVRs(memcpy)

    That's incorrect and dangerous. In the absence of rvalue references v3, you should write memberwise moves (with std::move).

    In C++98/03/11 (the terminology has changed, but the principles have remained the same), only PODs (Plain Old Data) can be bit-blasted with memcpy(). Classes with copy constructors/etc. are "non-POD" and attempting to memcpy them triggers undefined behavior. std::vector is definitely non-POD and therefore you cannot memcpy it.

    Chewie> I find it hard to find C++ resources that don't advocate this "inheritance based programming", and I'd love to hear your best practices about that.

    See Effective C++, Third Edition by Scott Meyers. It has a whole chapter on inheritance, and an item (38, looking at the table of contents - my copy is at home) dedicated to when you should use composition instead of inheritance.

    In general, I use inheritance when I need the one thing it does uniquely and well: runtime polymorphism. Otherwise, I'll reach for other C++ mechanisms first. For example, templates are better at compile-time polymorphism. What "compile-time polymorphism" means is when I want to write something that can work with many different types, but those types are all known at compile-time. The STL is the most obvious and famous example of this. vector<T> is a container of an arbitrary type T, but that type can be specified at compile-time. Making it a template allows it to handle these arbitrary types, without incurring any runtime overhead (everything is stamped out by the compiler and then inlined away, ideally).

    gh0st0nride> These core c++ video aren't being posted on visual c++ blog now?

    I write those link-posts when I have time (I just got back from 2 weeks of vacation). I'll try to remember to write them for videos in the future.

  • rhalbersmarhalbersma

    Here's a wish for a future lecture, which doesn't fit into the current Core C++ series, but which I would like to get your insights on anyway. How about showing us your development setup and routine? So e.g. teach us about your VC editor/compiler/linker settings, any shortcuts/plugins/external libraries you often use, perhaps some advanced debugging tricks, precompiled headers, etc. etc. In short, anything that would increase productivity/build times for the rest of us.

  • AlexanderAlexander

    Hi!

    I'm sorry if I'm too off-topic here, but I like C++ and there is something on my mind:
    The MSVC C++11 compliance is far too weak, and I have to admit that I expected more for VC11.

    I love the things the standard committee guys did to the language, and I am trying to incorporate the new features into my way of thinking in C++ instead viewing them as extensions.
    That works really well with GCC or Clang, but when it comes to Visual Studio, I have this moment way too often where I think "WTF? Why does this $41T not compile?!!".


    I'm sort of an open source guy and I'm all for supporting multiple platforms and compilers and I believe it's healthy to compile your code with several compilers, but I arrived at the point where I'm just about to drop support for MSVC in all my programs, regard it as broken and use MinGW for Windows compilation instead.

    @STL:
    Are your core compiler collegues finally working on C++, or do they still have "other assignments"?
    Can you make a guesstimation of when the "in-between-release" of the compiler that Herb Sutter mentioned in GoingNative will arrive?

    How do you find this situation? I could imagine you'd quite love to see more features to play with (variadic templates maybe?).

  • if overloaded operators are just syntactic sugar,
    please explain, why there is differences in the following code?

    class X{
    public:
    X& operator% (const X&) {
    std::cout << "member fun\n";
    return *this;
    }
    void f();
    };

    X& operator%( X& a, int)
    {
    std::cout << "global fun\n";
    return a;
    }

    void X::f()
    {
    X& a = *this;
    a % 1; // calls non-member function
    operator%(a, 1);//compiler error
    }

    thanks in advance Smiley

  • rhalbersmarhalbersma

    @gaya: if you recall episode 1 (name lookup), it should be clear that once the compiler finds operator% (even one with a different signature, which will be resolved during overload resolution) in the scope of class X, it stops looking for any other operator% in enclosing scopes. To call the free operator%, you can use ::operator%(a,1);

  • STLSTL

    I filmed Part 5, "Specializations", on Tuesday! :->

    rhalbersma> How about showing us your development setup and routine?

    You'll see some of this in Part 6. My environment is very austere - I use a plain text editor and I drive the compiler from the command line. (When building test cases, I manually invoke "cl /EHsc /nologo /W4". When building the compiler and libraries, I use our internal build system on the command line. At home, I use makefiles on the command line.)

    Alexander> Are your core compiler collegues finally working on C++, or do they still have "other assignments"?

    The compiler team is working on C++11 Core Language features right now. In Part 6, I'll show off an internal build of the compiler (driven from the command line, since IDE integration is a separate chunk of work). I'd love to say which features are being implemented, but I'm not allowed to do that yet.

    > Can you make a guesstimation of when the "in-between-release" of the compiler that Herb Sutter mentioned in GoingNative will arrive?

    We can't ever talk about release dates before they're publicly announced, sorry.

    > How do you find this situation? I could imagine you'd quite love to see more features to play with (variadic templates maybe?).

    I've often mentioned that as an STL maintainer, my work is greatly complicated by the lack of variadic templates. We've been imitating them with clever-but-horrible macro schemes since the VC9 Feature Pack.

    gaya> if overloaded operators are just syntactic sugar

    They are syntactic sugar for ordinary function calls, but they obey various special rules, especially for overload resolution.

    rhalbersma is correct, but to explain further:

    Given "a % 1", N3376 13.3.1.2 [over.match.oper]/3 explains that "For a unary operator @ with an operand of a type whose cv-unqualified version is T1, and for a binary operator @ with a left operand of a type whose cv-unqualified version is T1 and a right operand of a type whose cv-unqualified version is T2, three sets of candidate functions, designated member candidates, nonmember candidates and built-in candidates, are constructed as follows:". That's why both the member and non-member functions are considered by overload resolution (as a programmer would naturally expect).

    Given "operator%(a, 1)" which is written as an ordinary function call, 3.4.1 [basic.lookup.unqual]/8 notices that you're in a member function body, so as soon as it finds X::operator% it stops. In general, C++ really likes calling member functions, which is why the unqualified name lookup rules are written like this. The Argument-Dependent Lookup rules also follow this preference - both unqualified lookup and ADL are performed, and both sets of declarations found are tossed into the overload resolution arena, *except* that if unqualified lookup finds a class member, the ADL set is emptied out (3.4.2 [basic.lookup.argdep]/3 has the full story and lists a couple of other conditions).

    This is actually relevant in your scenario. Given the arguments (a, 1) the argument a is of type X which activates ADL. X lives in the global namespace, so ADL would search the global namespace and find operator%(X&, int) there - except that ADL has been disabled because unqualified lookup found a class member.

  • Dear @STL, thanks a lot for YOUR comprehensive explanation Smiley

  • Great Video again!

    Charles, any idea when the next video will be uploaded? Smiley

  • Thanks for all the very informative shows.


    Note sure if this is the best place but I wanted to suggest std::function and related topics for a show. I have just started replacing a bunch of old style functor stuff with this and have run into a lack of documentation, for instance answering a question like "what does a std::function actually store and how does that relate to copying/assignment of std::function objects" seems hard to find out without reading C++ library code which is not the easiest code to read!

  • Hi STL,

    I'm programming a directory iterator and I'm getting a error message, but not from my program, from the filesystem header; saying " '_Ptr' : is not a member of 'std::tr2::sys::basic_directory_entry<_Path>'.

    my call to path is

    sys::path fullpath = 
            sys::system_complete(sys::path(argv[1]));
    


    Thanks in advance for any assistance

    Tom

  • STLSTL

    davidhunter22> I wanted to suggest std::function and related topics for a show.

    I'll try to remember that for when I start doing videos on the STL again. If I forget, remind me. :->

    > I have just started replacing a bunch of old style functor stuff with this

    std::function is extremely useful, but it shouldn't be overused. For example, if you can template an algorithm on functor type, that is more efficient than having it take a std::function (which has inherent overheads).

    > "what does a std::function actually store

    Magic. But really, it just stores a copy of the functor you've given it.

    > and how does that relate to copying/assignment of std::function objects"

    The stored functor, including any state within, will be copied/assigned.

    > seems hard to find out without reading C++ library code which is not the easiest code to read!

    You shouldn't look at the guts of our implementation. If MSDN seems insufficient, you can look at the Working Paper for maximum accuracy.

    Tominator2005: This compiles for me with VC11 RTM:

    C:\Temp>type meow.cpp
    #include <filesystem>
    using namespace std;
    using namespace std::tr2::sys;
    
    int main(int argc, char * argv[]) {
        (void) argc;
        path fullpath = system_complete(path(argv[1]));
    }
    
    C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp
    meow.cpp
    
    C:\Temp>

    Send me a self-contained repro (like this) at stl@microsoft.com and I'll take a look.

  • @STL: Great stuff as usual, I love this core C++ series, please keep it coming !

    Best Regards,

    Russell

  • STLSTL

    Part 5: http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Core-C-/Stephan-T-Lavavej-Core-C-5-of-n

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.