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

Play Stephan T. Lavavej - Core C++, 5 of n

The Discussion

  • User profile image

    Excellent stuff. Part of the reason I enjoy Stephan's stuff so much is its cross platform nature. I get to play with this material in XCode 4.5.1  as well as Visual C++ 2012.

    More of Stephan please!

  • User profile image

    Oh, I was waiting for this new part from long time ago.
    Thank you Stephan.

  • User profile image

    Finally some "normal C++" video and as usual explained at the best level.

    Thanks for the series

  • User profile image

    Keep it coming Stephan ! Great work !

  • User profile image

    "When writing a specialization,
    be careful about its location;
    or to make it compile
    will be such a trial
    as to kindle its self-immolation."
    There is a poet in the Committee :-P

    Great joy watching you STL, as always! :-)

  • User profile image

    Great Big Smile another C++ video from Stephen.

    Template Specialization,
    ive seen a factorial specialization like that.


    template <int N>
    struct Factorial {
        enum { value = N * Factorial<N - 1>::value };
    template <>
    struct Factorial<0> {
        enum { value = 1 };
    // Factorial<4>::value == 24
    // Factorial<0>::value == 1
    const int x = Factorial<4>::value; // == 24
    const int y = Factorial<0>::value; // == 1

    Cant wait for part 5, and a meta programming tutorial will be fantastic

  • User profile image

    Thanks STL and Charles for this.


  • User profile image

    Thanks for another great episode STL. The gap between this and the previous video was so long I had forgotten about this series. Was delighted to see it on up on C9 yesterday.

  • User profile image

    Thank you for the video!

    I run lately into problem where I have to check inside class template if it was instantiatied with specific specialization (forgive me if I messed up explaining this), if it's a pointer to be more precisely.

    template <typename T> struct MyClass {
    MyClass() {
    //checking if T is a pointer, if so do some extra stuff
    //do other stuff
    } };

    My first thought was to use is_pointer<T> from type_traits which worked just fine, then I got asked to do this w/o type_traits so I ended up making help structs

    template <typename T> struct Help{ bool IsPointer(){return false;}};
    template <typename T> struct Help<T*>{bool IsPointer(){return true;}};

    or with static functions like you suggested in the video.

    My question is, whats acctually the best way to do this. I got into type_traits is_pointer guts and I noticed that it removes cv_qualifiers before comparasion if I remember correctly. Does it make it any better?

    Thanks in advance.

  • User profile image

    Ricode> template <typename T> struct Help{ bool IsPointer(){return false;}};

    Help<T>::IsPointer() is an ordinary member function. It can be tested at runtime, but not compiletime. (A static member function would behave identically.) When inspecting types in order to do things differently depending on the properties you find, you often need compiletime tests. For example, you might want to write *t + *u for pointers to integers, but t + u for integers themselves. Note that you cannot do this with a simple "if" test at runtime, because *t + *u is not valid for integers, and t + u is not valid for two pointers.

    <type_traits> provides compile-time answers with static const bool data members. (Other people use enums here.) This can be used, with mechanisms like tag dispatch (the preferred technique in VC's STL) or helper struct specializations, to perform compiletime tests.

    (C++11 constexpr changes things here.)

    > I got into type_traits is_pointer guts and I noticed that it removes cv_qualifiers before comparasion if I remember correctly.

    That's required by N3376 []/2: "For any given type T, the result of applying one of these templates to T and to cv-qualified T shall yield the same result." In English, is_pointer considers both "X *" and "X * const" to be pointers. The top-level cv-qualifier doesn't radically change the nature of the type. (If you care about top-level cv-qualification, you can always ask is_const.)

    However, the important thing here is that is_pointer<T> derives from either true_type or false_type. Therefore you can overload a helper function on true_type and on false_type, and pass it an is_pointer<T>() argument, and the desired overload will be selected. That will avoid calling the undesired overload, whose guts may not compile for the given type.

  • User profile image

    Thanks for explanation, haven't thought of that, was only testing is for simple "couts" to recive information, problem came when I tried to do some computations with types.

  • User profile image

    @geeyef: Sorry about that. I could have posted sooner, but alas I've been underwater on a large software project.


  • User profile image

    How can the posted example possibly be STL code without a Meow class? And where are my vectors of widgets?

    Great stuff as always from Stephan. :)

    Thanks for this, the past ones and all those in the past. If only we could clone you to do Channel9 monthly...

    Oh and a std::future<thank_you> for all those std::async(possible_videos).

  • User profile image

    HumanBlade> How can the posted example possibly be STL code without a Meow class?

    It isn't mine.  :->  Looks like it's from MSDN (the top comment is in their style).  Additionally, I wouldn't write code that leaked formatter1 and formatter2, even in a toy example.

    I filmed Part 6 yesterday!

  • User profile image

    Thank you.

  • User profile image
    Alex Krycek

    Thanks a lot.

  • User profile image

    DEAR STL , thanks for another GREAT GREAT GREAT video Smiley

  • User profile image

    I am so lucky to have such dedicated viewers. And to be able to make cat noises on camera.

  • User profile image

    Thanks for your great videos.
    I have a question about your presentation. When you talk about function specialization and overloading, you give the example:
    template <typename T> void meow(T);
    template <typename X> void meow(X*);
    If I understand your presentation correctly, these are two overloads, not template specialization. In this case, why the call to meow(double*) compiles? In my opinion, both functions are a perfect match (with T=double* and X=double), so the overload resolution should complain about that.

  • User profile image

    Correct, they're overloads, and after template argument deduction they're both exact matches. Ordinarily that would be ambiguous, but a tiebreaker steps in - "partial ordering of function templates" (N3376 [temp.func.order]). This process figures out whether one function template is "more specialized" than another. It closely imitates the effects of partial specialization for class templates.

    Partial ordering is easier for humans to do than compilers. Given two function templates f() and g(), f() is more specialized than g() if f() matches a strictly smaller infinite universe of stuff than g() does.  For example, meow(X *) is more specialized than meow(T).

    As a tiebreaker for equally good matches, overload resolution (13.3.3 []) prefers more specialized function templates.  (This is right next to the other tiebreaker rule, that non-templates are preferred to templates when they're equally good matches.)

    The way that a compiler performs partial ordering is really clever (but potentially confusing). Given f()'s function parameters, it generates imaginary function arguments and sees (via template argument deduction) whether it could call g() with them.  Then it reverses things, taking g()'s function parameters, generating imaginary function arguments, and seeing whether it could call f() with them.  (Partial ordering is a competition between function templates, without regard to the actual arguments you're passing.)

    Given meow(T), the compiler generates an imaginary argument of type TT and sees if it can call meow(X *) with it.  It can't.  Then given meow(X *), the compiler generates an imaginary argument of type XX *, and sees if it can call meow(T) with it.  It can.  This allows the compiler to determine, in just two steps, which function template (if any) matches a strictly smaller infinite universe of stuff, without actually generating an infinite number of possible arguments. Clever!

    For another example, if all capital letters are template parameters, and you have:

    kitty(A, B) // #1

    kitty(C *, D) // #2

    kitty(E, F *) // #3


    (int, int) selects #1.  (#2 and #3 fail template argument deduction.)

    (pointer, int) selects #2.  (#1 is also an exact match, but #2 is more specialized than #1.  #3 simply fails template argument deduction.)

    (int, pointer) selects #3.  (#1 is also an exact match, but #3 is more specialized than #1.  #2 simply fails template argument deduction.)

    However, (pointer, pointer) is ambiguous.  All three are exact matches, so partial ordering has to tiebreak.  #1 loses to both #2 and #3 so it's out of the picture.  However, #2 is not more specialized than #3 and vice versa, for the reasons explained above (both humans and compilers can see this).  This fact is a property of the function templates, it just wasn't relevant for the (int, int), (pointer, int), and (int, pointer) arguments.  Only the (pointer, pointer) arguments put #2 and #3 into competition with each other, at which point overload resolution tries to figure out which one is better.

    Adding a kitty(G *, H *) overload (#4) fixes things.  It doesn't change the fact that #2 isn't more specialized than #3 and vice versa, it just makes it irrelevant.  Given (pointer, pointer) arguments, #4 is more specialized than *all* of #1/#2/#3, so #4 wins.

    Hopefully that clarifies things.

  • User profile image

    Thank you, everything is clear now.

    In the video, your exemple with
    kitty(A, B) // #1
    kitty(C *, D) // #2
    kitty(E, F *) // #3
    was given using a class template specialization. I didn't know that the same rules applies to the function templates, even in the case of overloading.

    Clever compiler.

  • User profile image
  • User profile image
    Uri London

    Stephan, your talk basically discussed one kind of template specialization ... basically when T (the template argument) is a pointer.
    In addition to: template<typename T> struct S<T*> ..., I'm familiar with T[] and T&. What would be helpful if you have a talk discussing other specialization options, such as T is derived from something, or T has a certain trait (using <type_traits> header file).

    Also, I don't think the following was discussed enough. If X is a templates, and A and B are two classes, with B derived from A, it is not true that X<A> is derived from X<B>. Same is going with template specialization - which has nothing to do with inheritance. However, my question is what can we do to workaround this. For example, I've X<typename T> a class template, and I've X<int> a specialization template. Is there any way I can have some of the methods of the general template X<T> in X<int> without retyping it?

  • User profile image
    Zahir Tezcan

    You skimmed over extern templates and you told that you really didn't use such thing. Please imagine this, I really want to make some dynamic library for other people to use, but almost all of the C++ standard library is template classes and I am not able to safely export anything from my library. There are a lot of articles around the web and all of them tells me how to hide the VisualStudio warning, the thing is problem persists. How can I use something like vector or shared_ptr if I cannot export them safely?

    Like this:

    class MY_API MyClass
        std::vector<int> indices;

    where MY_API is __declspec(dllimport/dllexport) thingy. How do you tackle this problem?

  • User profile image
    Dave Allan

    This is beautiful. Thank you so much for sharing. I finally get it!!

  • User profile image

    A great talk!! Angel I appreciate the crisp and detailed explanation. 

Add Your 2 Cents