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

Download

Right click “Save as…”

Part 6 is a special episode in which Stephan takes a look at the latest C++11 features that were just added to the Visual C++ compiler:

Variadic templates 
Raw string literals
Explicit conversion operators
Default template arguments for function templates
Delegating constructors
Uniform initialization

This compiler is now available as a Customer Technology Preview release to everyone. If you want to test-drive this new compiler too, download it from here: http://aka.ms/vc-ctp. More details on this release are available on Visual C++ Blog (http://blogs.msdn.com/vcblog/).

Make sure to watch Herb Sutter's C++ keynote at BUILD 2012.

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

Tags:

Follow the Discussion

  • Herb Sent me here! Big Smile

  • Eric AguiarHeavens​Revenge Know Thyself

    Finally... Uniform Initialization FTW!!!!!!!!!!! Can't wait for Initializer lists to make it in at long last!!! Also STL if you want a good editor suggestion, my favourite & recommendation = EmEditor http://www.emeditor.com/ , it uses boost shows it proudly in "About" Smiley

    It's a 64-Bit editor which has multiple very sweet properties, Visual Studio Project Plugin and tons of more plugins, snippets for countless languages, auto-completion for... everything even based on previous files used, uses ZERO (0) CPU cycles when not in use AND it can handle many-millions of lines of text without slowing down even doing vertical editing on line *million Tongue Out.

    But alas, try it out and deem it for yourself!

  • M2tMM2tM

    Let me suggest sublime text 2 if you need a generic editor, it's quite good.

    Of course, I prefer visual studio when doing c++ development.

  • STLSTL

    I like my editor just fine, but thank you for the suggestions.

  • Jesse GoodJesse Good

    @STL:

    Could you let us know any possible date for an updated Standard Library?
    I'm still waiting for the day when I can write std::vector<int> v{1, 2, 3}. (I apologize if this was mentioned in the video and I didn't catch it).

  • StevenSteven

    Thank you very much for your presentation. These C++11 features will be very helpful, when will we see these features released into final product? VS2012 SP(s)? It will surely smooth our ability to compile for Windows targets as well as targets using the more recent GCC releases containing these features.

  • @STL Do you happen to know if there is a define I can use to feature detect?
    For example,
    #if CTP > 1
    #define VARIADIC_TEMPLATES_SUPPORTED
    #endif
    Thanks!

  • rhalbersmarhalbersma

    A great day for C++, and another great talk from you, thanks!

    After watching Herb's and your talk, I installed the VC++ CTP and tested some features. The default function template argument feature worked as expected, but the variadic templates didn't go quite so smoothly. The make_unique code in your talk works as expected.

    But I also tested some of my own code for which VC++ CTP failed to compile with the error: error C2752 (more than one partial specialization matches the template argument list).

    Code sketch:

    // primary template declaration
    template<typename>
    struct init;

    // partial specialization declarations
    template
    <
    template<typename, typename, typename...> class Predicate,
    typename Board,
    typename... Args
    >
    struct init< Predicate<Board, boost::mpl::_1, Args...> >;

    Now the error came from a call init< SomePred< Bla, boost::mpl::_1> >
    so with a zero-sized argument pack. This is code for which the explicit list of partial specialization with 0, 1 and 2 arguments works, and for which your MinGW distro does compile and run collectly on the both the variadic and 0-1-2 versions.

  • STLSTL

    Jesse Good> Could you let us know any possible date for an updated Standard Library?
    Steven> when will we see these features released into final product?

    I am not allowed to even hint at release dates before they're publicly announced, sorry. (I can quote VCBlog: "Herb also announced that more information about the next batch of C++11 features would be coming in the first half of 2013.")

    I can talk about almost anything else, though. I'm personally working with Dinkumware to pick up their updated STL machinery.

    ProgramMax> Do you happen to know if there is a define I can use to feature detect?

    Test _MSC_FULL_VER. It is 170050727 for VC11 RTM and 170051025 for this CTP.

    rhalbersma: Works for me:

    C:\Temp>type meow.cpp
    template <typename T> struct Init {
        static_assert(sizeof(T) == 0, "Init<T> chosen.");
    };
    
    struct X { };
    
    template <
        template <typename, typename, typename...> class Predicate,
        typename Board,
        typename... Args
    > struct Init<Predicate<Board, X, Args...>> {
        static_assert(sizeof(Board) == 0, "Init<Predicate<Board, X, Args...>> chosen.");
    };
    
    template <typename, typename, typename...> struct SomePred { };
    
    Init<SomePred<int, X>> i;
    
    C:\Temp>cl /EHsc /nologo /W4 /c meow.cpp
    meow.cpp
    meow.cpp(12) : error C2338: Init<Predicate<Board, X, Args...>> chosen.
            meow.cpp(17) : see reference to class template instantiation 'Init<SomePred<int,X,>>' being compiled

    As always, please provide a self-contained repro.

  • rhalbersmarhalbersma

    @Stephan,

    Sorry not providing a small self-contained example but the code is dependent on some pretty heavy Boost.MPL stuff. For what it's worth: the variadic version compiles and runs fine in Release mode, but generates the partial specialization ambiguity in Debug mode only. As I said, it works fine on your latest MinGW, so if this could possibly be a VC bug, I am willing to make the effort of providing a stripped-down repo that isolates the behavior. Let me know what the appropriate channels would be for that.

  • mwumwu

    Thank you for the talk, I really enjoy your series! :)

    I've tried playing around with the uniform initialization and encountered an issue that puzzles me. Please consider the following code:

    #include <fstream>
    int main()
    {
    std::ofstream file1("test1"); //ok
    std::ofstream file2{"test2"}; //compile error
    return 0;
    }

    error C2440: 'initializing' : cannot convert from 'initializer-list' to 'std::basic_ofstream<char,std::char_traits<char>>'

    Shouldn't the brace initialization just call the ofstream(const char*) constructor like the line above? Is this a compiler bug, issue caused by not updated library or am I misunderstanding the uniform initialization?

  • RicodeRicode

    Thank you for the video!

  • STLSTL

    rhalbersma> the variadic version compiles and runs fine in Release mode, but generates the partial specialization ambiguity in Debug mode only.

    That indicates library involvement (STL or Boost). By itself, the compiler doesn't care about debug mode.

    > if this could possibly be a VC bug, I am willing to make the effort of providing a stripped-down repo that isolates the behavior.

    That would be great. You can report it through Microsoft Connect, or directly to me at stl@microsoft.com . (Note that while I'm willing to file compiler bugs in our internal database on behalf of people, (1) it's slightly more work for me, and (2) you won't get a direct response from the compiler team when it's resolved.)

    An ideal repro would use the Core Language only. Using the Standard Library makes it harder for the compiler devs to figure out what's going on, but they can still do it. If you absolutely can't figure out how to repro it without Boost, then that's better than nothing, although Boost generates very complicated translation units. (You just need to provide the exact Boost version you're using - for other libraries you would have to provide preprocessed files to the compiler team, but we have Boost.)

    mwu> Is this a compiler bug

    Yep. Great find - it's severe and you're the first reporter as far as I can tell. I've filed it as DevDiv#510870 "[Milan] list-initialization should be treated as direct-initialization" with the following Core Language-only repro, plus the Standardese that says it should work:

    C:\Temp>type meow.cpp
    /* N3376 8.5 [dcl.init]/15:
    "The initialization that occurs in the forms
    T x(a);
    T x{a};
    as well as in [...] is called direct-initialization." */
    
    struct Foo {
        explicit Foo(int) { }
    };
    
    int main() {
        Foo f{0};
    }
    
    C:\Temp>cl /EHsc /nologo /W4 meow.cpp
    meow.cpp
    meow.cpp(12) : error C2440: 'initializing' : cannot convert from 'initializer-list' to 'Foo'
            Constructor for struct 'Foo' is declared 'explicit'

    (Direct-initialization can invoke explicit constructors, while "T x = a;" copy-initialization can't.)

    As an aside, when looking at compiler warnings and errors, you should always make sure that you're not missing any "continuation messages" like the indented line here. These typically contain additional information necessary to understand what the compiler's complaining about, especially template instantiation context. This is one of the reasons that IDEs and build systems frustrate me - some of them strip continuation messages from their warning/error list, and you have to go to the full output log to see them.

  • Will having explicit conversion operators replace std::string::c_str()? I can see the conversion operating causing problems with things like printf. Outside of type unsafe functions, would there be any other gotchas?

  • PeterPeter

    Doesn't the array version of unique_ptr need an array deleter?

  • mkhmkh

    Thanks for the great video. Any chance to see the advanced variadic template code? Hope to learn something new. Thanks alot.

  • Benjamin LindleyBenjamin Lindley

    What are the rules regarding overload resolution when you have 2 constructors, one which takes std::initializer_list<T>, and another which takes 1 or more T? For example, if I create a vector of int, and initialize it with {10,10}, does that create a vector of 2 ints with value 10? Or does it create a vector of 10 ints with value 10? My tests indicate the former, but is it the case that std::initializer_list<> will always be preferred if it matches, or are there more complex rules?

  • Xeoc9xeo Sanity is just a mask

    Great video and great features, thanks a bunch!

    (Direct-initialization can invoke explicit constructors, while "T x = a;" copy-initialization can't.)

    I find it kinda sad that

    1
    return {some_args};

    aswell as

    1
    f({some_args})

    don't count as direct-initialization and as such can't invoke explicit constructors. Especially annoying for unique_ptr and tuple.

    @Benjamin Lindley: A good example here would be the following gotcha with list-initialization:

    1
    std::vector<int> v{5};
    assert(v.size() == 1 && v.front() == 5);

    The standard explicitly demands that this happens in §13.3.1.7/1:

    When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

    •  Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
    • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

    And a little note in §8.5.4/2:

    [ Note: Initializer-list constructors are favored over other constructors in list-initialization (13.3.1.7).—end note ]

  • Ben HansonBen Hanson

    I tried STL's code from the video using GCC and got the following output:

    4IntsIILi2ELi2ELi3ELi3ELi5ELi7ELi11ELi11ELi11ELi11ELi13ELi13ELi17ELi19ELi19ELi23ELi29ELi29ELi29ELi31ELi37ELi37ELi41ELi43ELi47ELi47ELi53ELi59ELi59ELi61ELi61ELi67ELi71ELi73ELi79ELi79ELi83ELi83ELi83ELi89ELi89ELi89ELi97EEE

    I'm not sure if that's expected, or whether I've not copied the code quite right.

    Code:

    #include <iostream>
    #include <typeinfo>

    template<int... Vals> struct Ints {};

    template<typename Ints1, typename Ints2> struct Concat;

    template<int... Vals1, int... Vals2> struct Concat<Ints<Vals1...>, Ints
    <Vals2...>> {
    typedef Ints<Vals1..., Vals2...> type;
    };

    template<typename Ints1, typename Ints2, bool Done> struct BisectHelper;

    template<int... Vals1, int... Vals2> struct BisectHelper<Ints<Vals1...>,
    Ints<Vals2...>, true> {
    typedef Ints<Vals1...> first;
    typedef Ints<Vals2...> second;
    };

    template<int... Vals1, int X, int... Vals2> struct BisectHelper<Ints
    <Vals1...>, Ints<X, Vals2...>, false> :
    public BisectHelper<Ints<Vals1..., X>, Ints<Vals2...>,
    (sizeof...(Vals1) + 1 >= sizeof...(Vals2))> {};

    template<typename Ints1> struct Bisect;

    template<int... Vals> struct Bisect<Ints<Vals...>> :
    public BisectHelper<Ints<>, Ints<Vals...>, sizeof...(Vals) == 0> {};

    template<typename Ints1, typename Ints2> struct Merge;

    template<> struct Merge<Ints<>, Ints<>> {
    typedef Ints<> type;
    };

    template<int A, int... Vals1> struct Merge<Ints<A, Vals1...>, Ints<>> {
    typedef Ints<A, Vals1...> type;
    };

    template<int B, int... Vals2> struct Merge<Ints<>, Ints<B, Vals2...>> {
    typedef Ints<B, Vals2...> type;
    };

    template<bool TakeB, typename Ints1, typename Ints2> struct MergeHelper;

    template<int A, int... Vals1, int B, int... Vals2> struct Merge<Ints<A,
    Vals1...>, Ints<B, Vals2...>> :
    public MergeHelper<(B < A), Ints<A, Vals1...>, Ints<B, Vals2...>> {};

    template<int A, int... Vals1, int B, int... Vals2> struct MergeHelper
    <false, Ints<A, Vals1...>, Ints<B, Vals2...>> :
    public Concat<Ints<A>, typename Merge<Ints<Vals1...>, Ints<B, Vals2...>>::type> {};

    template<int A, int... Vals1, int B, int... Vals2> struct MergeHelper<true,
    Ints<A, Vals1...>, Ints<B, Vals2...>> :
    public Concat<Ints<B>, typename Merge<Ints<A, Vals1...>,
    Ints<Vals2...>>::type> {};

    template<typename Ints1> struct SortHelper;

    template<> struct SortHelper<Ints<>> {
    typedef Ints<> type;
    };

    template<int A> struct SortHelper<Ints<A>> {
    typedef Ints<A> type;
    };

    template<int A, int B, int... Vals> struct SortHelper<Ints<A, B, Vals...>>
    {
    private:
    typedef Bisect<Ints<A, B, Vals...>> bisect;

    typedef typename bisect::first unsorted_first;
    typedef typename bisect::second unsorted_second;

    typedef typename SortHelper<unsorted_first>::type sorted_first;
    typedef typename SortHelper<unsorted_second>::type sorted_second;

    public:
    typedef typename Merge<sorted_first, sorted_second>::type type;
    };

    template<int... Vals> struct Sort :
    public SortHelper<Ints<Vals...>> {};

    int main(int argc, char **argv)
    {
    std::cout << typeid(Sort<11, 13, 5, 79, 73, 47, 31, 89, 2, 97, 41, 11, 61,
    19, 29, 29, 59, 67, 89, 53, 2, 37, 43, 17, 47, 89, 79, 23, 61, 83, 7,
    83, 11, 3, 13, 3, 11, 59, 71, 37, 29, 19, 83>::type).name() << std::endl;
    }

  • STLSTL

    NicoNevrakis> Will having explicit conversion operators replace std::string::c_str()?

    std::string hasn't been changed here. "explicit const char *()" wouldn't permit meow(const char *) to be called with a std::string.

    > I can see the conversion operating causing problems with things like printf.

    printf() doesn't invoke conversions, either implicit or explicit. It just blasts bits, which is why non-PODs (like std::string) can't be given to it.

    Peter> Doesn't the array version of unique_ptr need an array deleter?

    It already has one - unique_ptr<T[]> is a partial specialization, distinct from the primary template unique_ptr<T> for pointers to single objects.

    mkh> Any chance to see the advanced variadic template code?

    I might present it in Part 7, but apparently I have very dedicated viewers who are willing to freeze-frame and transcribe stuff as I scroll through it...

    Ben Hanson> I tried STL's code from the video using GCC and got the following output:

    Pipe that through "c++filt -t". GCC's type_info::name() returns mangled names.

  • rhalbersmarhalbersma

    @Stephan,

    I think my problem can be isolated to Boost.MPL (and more particularly to a BOOST_MPL_AUX_ASSERT_NOT_NA macro in the template struct arg<1> in the file boost/mpl/aux_/preprocessed/plain/arg.hpp), but I will wait till Boost 1.52.0 comes out this week, to see if the problem persists. There was a bug report about nested BOOST_MPL_ASSERT last month (which you commented on on the Boost mailinglist), so perhaps it's connected to that.

  • rhalbersmarhalbersma

    Apart from waiting until Boost 1.52.0, I suppose building Boost 1.51.0 with commenting out some of the BOOST_NO_CXX11_FEATURE macros with FEATURE = EXPLICIT_CONVERSION_OPERATORS, RAW_LITERALS, VARIADIC_TEMPLATES, UNIFIED_INITIALIZATION_SYNTAX (in the file boost/config/compiler/visualc.hpp) might be a good idea. I'll report back when all else fails.

  • Ben HansonBen Hanson

    @STL: Thanks Stephan, I'll give that a go. Thanks for your lectures! :-) Oh, and +1 for you doing an MPL series.

  • STLSTL

    rhalbersma: Boost 1.52.0 was released today. :->

    Ben Hanson: I'm glad you like them. However, as I haven't used Boost.MPL, I won't be doing any episodes about it.

  • Ben HansonBen Hanson

    Hi Stephan,

    No, I wasn't referring to boost. Rather some episodes on home grown meta-programming (particularly when VC++ supports constexpr).

  • Ben HansonBen Hanson

    Actually, I should have said TMP rather than MPL. My mistake!

  • std::vector is the "default" and mostly used container in C++. Not having support for vector initializer list is a big negative point.

  • STLSTL

    Ben Hanson: I've covered type traits and mentioned tag dispatch in the past, but I might do an episode about some template metaprogramming I had to do in std::find() which was pretty tricky.

    Marius Bancila> Not having support for vector initializer list is a big negative point.

    I know. I'm working with Dinkumware to pick up this support in the very near future.

  • DivyeDivye

    @STL: Just out of curiosity, what editor do you use? (Emacs?)

  • DivyeDivye

    Never mind. Asked too soon... Saw your environment in the video.

  • MelMel

    Can you explain how to set the path etc so I can use the compiler from the command line? Thanks!

  • STLSTL

    With VC11 RTM and the CTP installed in their default locations:

     

    "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\vcvarsall.bat" x86
    set PATH=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\bin;%PATH%
    set INCLUDE=C:\Program Files (x86)\Microsoft Visual C++ Compiler Nov 2012 CTP\include;%INCLUDE%

  • SongSong

    So can this be done more effective now and with reduced code generation or will we still have to wait for the next version of C++ ?

    http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Advanced-STL/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-6-of-n#c634477066580000000

    http://channel9.msdn.com/Series/C9-Lectures-Stephan-T-Lavavej-Advanced-STL/C9-Lectures-Stephan-T-Lavavej-Advanced-STL-6-of-n#c634477472460000000

    This is quite an interesting problem, i think.
    more code generation vs dynamic memory allocation vs unsafe hackish macro tricks

    For example std::function is easy to use but it cause big code generation foot print so not very good for general use like in the example above.

    Always hard to work with the compiler and allow it to optimize.

  • RosterRoster

    https://twitter.com/idBrianHarris/status/262927904428666880

    Spotted this question of why a game company used custom containers instead of STL. This was the answer given:
    "Mostly performance and debug-ability. We re-evaluate STL every few years but so far various factors have prevented switching."

    @STL: Do you have any comments on this ?

    When a big very successful game company say this, will microsoft still ignore the feedback like with windows 8 ?

  • dumdumdumdum

    @STL
    Doesn't your eye(s?) get tired quicken when not using colors ?
    It helps me a lot using collor

  • STLSTL

    Song> So can this be done more effective now and with reduced code generation or will we still have to wait for the next version of C++ ?

    I am thinking about proposing "guard-lambdas" to the Evolution Working Group.

    > For example std::function is easy to use but it cause big code generation foot print so not very good for general use like in the example above.

    Generally, when you need std::function, its space and time costs are reasonable. It just shouldn't be overused. The guard case is tricky because you really don't want to allocate memory.

    Roster> "Mostly performance and debug-ability. We re-evaluate STL every few years but so far various factors have prevented switching."

    The STL is a general-purpose library, so it can't be perfectly tuned for every possible scenario. However, we try to make it as fast as possible given that constraint. Also, the STL supports custom allocators, which can have a significant impact on performance.

    As for debuggability, we've taught the VS IDE how to "visualize" STL containers. The red-black tree that powers std::map/etc. is a very complicated data structure, but the visualizers make it look like a plain old sequence.

    > When a big very successful game company say this, will microsoft still ignore the feedback like with windows 8 ?

    If anyone can point out specific things that our STL implementation could be doing faster or better, I can do something about them (or explain why the Standard prevents us from behaving differently).

    dumdum> Doesn't your eye(s?) get tired quicken when not using colors ?

    Nope! Syntax highlighting doesn't help me understand code better. In fact, it's mostly visual noise that distracts from what's truly important.

    (I can also read English without having nouns and verbs colored differently.)

  • Kerrek SBKerrek SB

    Thanks for the great video!

    You mentioned an addition to the standard coming in C++14 which lets you write just "less<>". Could you perhaps give a few more details?

  • Kerrek SBKerrek SB

    There's always something new I learn each time I watch one of these videos; I can't thank you enough for making them!

    I never realised that make_unique requires special treatment for arrays. Here is my attempt, which doesn't use helpers:

    http://ideone.com/25LXe1

  • STLSTL

    Kerrek SB> Could you perhaps give a few more details?

    See my proposal at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm . It was voted directly into the Working Paper without any revisions. See the updated Working Paper at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf .

    In a recent checkin, I implemented my functors in our Milan branch, and James McNellis used less<> and equal_to<> to chop out 25% of the code in <algorithm>.

    > There's always something new I learn each time I watch one of these videos; I can't thank you enough for making them!

    I'm glad to hear that!

    > Here is my attempt, which doesn't use helpers:

    That's problematic. Consider vector<int>(10, 1729). That's a temporary vector containing ten copies of 1729. N3485 20.7.2.2.6 [util.smartptr.shared.create] requires make_shared<vector<int>>(10, 1729) to return a shared_ptr to a vector containing ten copies of 1729. However, your make_unique<vector<int>>(10, 1729) returns a unique_ptr to a vector containing two elements (10 followed by 1729), because you used braces for the scalar form.

  • KerrekSBKerrekSB

    STL> See my proposal at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3421.htm . It was voted directly into the Working Paper without any revisions. See the updated Working Paper at http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3485.pdf .

    Thanks - someone already posted the entire list of proposals in the StackOverflow chat, so I already discovered it. Good to have a new version of the draft standard!

    STL> me> Here is my attempt, which doesn't use helpers:
    >
    STL> That's problematic.

    Ah, of course. Brace-initiaziation doesn't necessarily call any matching constructor if there's an explicit initializer_list constructor. I should really have thought about this more.

    It's time to update my make_unique then. Thanks for the explanation!

  • xarts19xarts19

    Hi Stephan,
    My colleagues and I jumped onto the new compiler right away and are very happy with new features (especially variadic templates).
    However, I encountered one problem.
    I was wrapping some classes for use in Lua, and, although free functions work great, this approach don't really work for member functions (both static and non-static).
    Functions have to have a specific signature to be called from Lua, so I did something like this (simplified example):

    struct A
    {
    static int f1(int a, int b)
    {
    return a + b;
    }
    };

    int f2(int a, int b)
    {
    return a + b;
    }

    template <typename Sig, void(*fnc)(void)>
    struct wrapper;

    template <void(*fnc)(void), typename T_Ret, typename... T_Args>
    struct wrapper<T_Ret (T_Args...), fnc>
    {
    static bool apply()
    {
    // get some ints here from the Lua stack
    int a = lua_get();
    int b = lua_get();

    typedef T_Ret (fnc_ptr*)(T_Args...);
    int res = ( (fnc_ptr)fnc )(a, b);

    // push result onto the stack
    lua_push(res);
    return 1; // number of pushed arguments
    }
    };

    int main()
    {
    bool res;
    res = wrapper<decltype(A::f1), (void(*)(void))A::f1>::apply(); // error
    res = wrapper<decltype(f2), (void(*)(void))f2>::apply(); // compiles ok
    return 0;
    }

    I do some other template metaprogramming to retrieve the arguments depending on their types, and push result in a correct way based on its type, but it all works great and have nothing to do with the problem.
    So, why are static functions different from free functions?
    Hope you can help me.
    Have a great day!

  • xarts19xarts19

    Ok, I figured it out.

    I changed "decltype(A::f1)" to "decltype(&A::f1)" which changed its output from "int(int, int)" to "int (__cdecl *)(int,int)". And I changed

    template <void(*fnc)(void), typename T_Ret, typename... T_Args>
    struct wrapper<T_Ret (T_Args...), fnc>

    to

    template <void(*fnc)(void), typename T_Ret, typename... T_Args>
    struct wrapper<T_Ret (*)(T_Args...), fnc>

    Everything works now.
    But I'm still curious as to why the first time, template wasn't instantiated for int(int, int) type.

  • Hi,

    One topic I'd like to see is see an Advanced Series on Data Structures.
    For Example, Linked Lists and Maps. 
    [edit] Forget that Smiley I can look up data structures on you tube Smiley

    As always a great series Smiley

    Keep up the good work

    Tom

  • STLSTL

    xarts19: That's a compiler bug. I've filed DevDiv#519532 "[Milan] decltype(Foo::bar) doesn't work for static member functions" with this reduced repro:

    C:\Temp>type meow.cpp
    template <typename A, typename B> struct is_same {
        static const bool value = false;
    };
    
    template <typename T> struct is_same<T, T> {
        static const bool value = true;
    };
    
    struct Foo {
        static void bar() { }
    };
    
    static_assert(is_same<decltype(&Foo::bar), void (*)()>::value, "This works.");
    
    static_assert(is_same<decltype(Foo::bar), void ()>::value, "This explodes.");
    
    C:\Temp>cl /EHsc /nologo /W4 /c meow.cpp
    meow.cpp
    meow.cpp(15) : error C2338: This explodes.

    Tominator2005: I covered lists and maps in my Intro STL series. :->

  • xarts19xarts19

    Thanks! Great videos, keep up the good work.

  • I know, i saw them Smiley I meant an Advanced lecture on Linked Lists and Maps.
    How they work etc, but like I said Stephen, it doesn't matter anymore :->

  • ChrisChris

    Stephan,

    Great talk. However, I was surprised to learn from your talk that for a function:

    void foo(std::unique_ptr<int>, std::unique_ptr<int>);

    the passing of temporaries in this form is unsafe:

    foo(std::unique_ptr<int>(new int(1),
    std::unique_ptr<int>(new int(2));

    I know the order of evaluation of arguments is unspecified (in particular, it is unspecified whether the first or second argument is evaluation first), but I would have thought that the compiler should not be allowed to stop evaluation of any particular argument half-way through.

    There must be shed loads of unsafe code in consequence. Isn't this a defect in the standard? And can you point to the part of the standard which permits this partial evaluation?

    Chris

  • STLSTL

    Chris> I would have thought that the compiler should not be allowed to stop evaluation of any particular argument half-way through.

    The Standard doesn't think of it like that. Given something like outer(alpha(foo(), bar()), beta(woof()), gamma(meow(), purr())), the Standard sees a bunch of subexpressions. (In this case, they're all function calls.) The ground rule is that the order of evaluation of these subexpressions is unspecified, with specific exceptions. One exception is simple: the arguments to a function must be evaluated before that function is called. Therefore, we know that meow() and purr() will be called before gamma() is called, although this rule does not constrain things further. Another exception is that function calls cannot be interleaved. While gamma() is being called, the program is not allowed to stop what it's doing, go evaluate some of foo(), bar(), woof(), alpha(), or beta(), and then resume doing whatever gamma() does. (That is obviously forbidden because it would wreak havoc.)

    Notably, these constraints do not achieve what you expected them to achieve. The Standard permits this order of evaluation: foo(), purr(), meow(), gamma(), woof(), bar(), beta(), alpha(), outer().

    > There must be shed loads of unsafe code in consequence.

    People write bad code all the time. In this case, the "unnamed smart pointer gotcha" is not especially deadly (if no exceptions are thrown while raw pointers are "in the air", then nothing bad happens). Worse things happen when people try to cram too many increments, etc. into a single expression and violate the closely related Multiple Modification Rule (which triggers undefined behavior).

    > Isn't this a defect in the standard?

    This goes all the way back to C. Of course, C didn't have exception handling, but the unspecified order of evaluation is still observable (e.g. if the function calls do I/O like printf(), or they can all observe some variable - like a global, or if they've all been given &x).

    Nothing fundamental prevents C and C++ from specifying a deterministic order of evaluation here, or even a slightly more constrained order. However, it was left very weakly specified in order to permit compiler optimizations.

    > And can you point to the part of the standard which permits this partial evaluation?

    C++98/03 talked about "sequence points", while C++11 uses different terminology. N3485 1.9 [intro.execution]/13: "Sequenced before is an asymmetric, transitive, pair-wise relation between evaluations executed by a single thread (1.10), which induces a partial order among those evaluations. Given any two evaluations A and B, if A is sequenced before B, then the execution of A shall precede the execution of B. If A is not sequenced before B and B is not sequenced before A, then A and B are unsequenced. [ Note: The execution of unsequenced evaluations can overlap. —end note ] Evaluations A and B are indeterminately sequenced when either A is sequenced before B or B is sequenced before A, but it is unspecified which. [ Note: Indeterminately sequenced evaluations cannot overlap, but either could be executed first. —end note ]"

    /15: "Except where noted, evaluations of operands of individual operators and of subexpressions of individual expressions are unsequenced. [ Note: In an expression that is evaluated more than once during the execution of a program, unsequenced and indeterminately sequenced evaluations of its subexpressions need not be performed consistently in different evaluations. —end note ] The value computations of the operands of an operator are sequenced before the value computation of the result of the operator. If a side effect on a scalar object is unsequenced relative to either another side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. [...omitted example of the Multiple Modification Rule...] When calling a function (whether or not the function is inline), every value computation and side effect associated with any argument expression, or with the postfix expression designating the called function, is sequenced before execution of every expression or statement in the body of the called function. [ Note: Value computations and side effects associated with different argument expressions are unsequenced. —end note ] Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.(9) Several contexts in C++ cause evaluation of a function call, even though no corresponding function call syntax appears in the translation unit. [ Example: Evaluation of a new expression invokes one or more allocation and constructor functions; see 5.3.4. For another example, invocation of a conversion function (12.3.2) can arise in contexts in which no function call syntax appears. —end example ] The sequencing constraints on the execution of the called function (as described above) are features of the function calls as evaluated, whatever the syntax of the expression that calls the function might be."

    Footnote 9: "In other words, function executions do not interleave with each other."

    In C99 (I do not have the C89 Standard), this is specified by 6.5.2.2 "Function calls"/10: "The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call."

  • ChrisChris

    Stephan,

    Thanks for your fulsome explanation. So you can say that the call to operator new() for any one parameter is sequenced before the construction of the temporary unique_ptr object for that parameter, but nothing about the relationship of these operations with respect to the other parameter.

    I now realize that I knew the sequencing rules to which you refer, but I had never applied that theoretical knowledge to such an "obviously correct" (not) usage.

    It all seems a bit tacky. A lot of code I had assumed was exception safe (including some I have written) is not. I feel slightly shocked and, to be honest, disappointed. I am not certain that this is how a modern programming language which throws exceptions should behave.

    It is also pretty egregious that in view of this the standard does not provide a make_*() variant for all its library classes which manage resources.

    Chris

  • STLSTL

    > I am not certain that this is how a modern programming language which throws exceptions should behave.

    The problem is that "new" is not modern - it returns an owning raw pointer which is highly radioactive.

    > It is also pretty egregious that in view of this the standard does not provide a make_*() variant for all its library classes which manage resources.

    Only make_unique is missing, and I'm planning to write a proposal for it.

  • ChrisChris

    > The problem is that "new" is not modern - it returns an owning raw pointer which is highly radioactive.

    That is the problem with memory resources[1], which on systems with swap and advanced commit is actually rarely an issue: for them, 'new' is fine as you are not going to get std::bad_alloc thrown in any case where it means anything. However, there are things other than memory resources in play as soon as you bring exceptions into a language.

    Anyway, thanks for your thoughtful response.

    Chris

    [1] I personally think that for memory resources (i) garbage collection, which is available for C++ in well implemented libraries for all major platforms, is often a better option, and (ii) where you want to use references counts or unique references as a poor man's garbage collector in the presence of exceptions, as standard C++ does, there is no need to make things unnecessarily difficult, as standard C++ also does.

  • Hey STL, 

    I managed to write the Linked List using unique_ptrs finally, it was me who emailed you!
    Took me a fair while though.

    Here's my code.

    #include <memory>
    #include <utility>
    using namespace std;
    
    template <typename T>
    struct Node{
        T data;
        unique_ptr<Node<T>> next;
    public:
        Node(T val):data(val),next(nullptr){}
        Node(T val,unique_ptr<Node>&& next){
            this->next = move(next);
        }
        Node(T val,unique_ptr<Node>& next){
            this->data = val;
            this->next.swap(new Node<T>(next->data));
        }
        void insertAfter(T& data){
            next = unique_ptr<Node<T>>(new Node<T>(data,next));
        }
    
    };
    
    template <typename T>
    class SList{
    private:
        unique_ptr<Node<T>> head;
        int size;
    public:
        SList(){
            size = 0;
            head = nullptr;
        }
    
        void insertFront(T val){
                head = unique_ptr<Node<T>>(new Node<T>(val,head));
    
                size++;
        }
    
    };

    and the main program

    
    
    #include <iostream>
    #include "Node.h"
    using namespace std;
    int main(){
    
        SList<int> myList;
        int f = 3;
        int s = 4;
        myList.insertFront(f);
        myList.insertFront(s);
    
    
        return 0;
    }


    Keep up the good work Smiley
    Tom

  • STLSTL

    Chris> However, there are things other than memory resources in play as soon as you bring exceptions into a language.

    And they just have to be managed by objects with destructors. I'm not a fan of iostreams, but fstream does this for FILE *.

    > I personally think that for memory resources (i) garbage collection, which is available for C++ in well implemented libraries for all major platforms, is often a better option

    The problems with GC are that it doesn't handle non-memory resources, and it involves a space-time tradeoff (you can make it fast at the cost of significantly increased space consumption, or vice versa).

    > where you want to use references counts or unique references as a poor man's garbage collector in the presence of exceptions, as standard C++ does, there is no need to make things unnecessarily difficult, as standard C++ also does.

    Stack-based resource management (vector, unique_ptr, fstream, etc.) is uniform (handling all resources) and optimal (zero costs). shared_ptr involves minor space and time costs, but it is uniform and does not result in significantly increased space consumption.

    I consider abominations like "finalizers" to be unnecessarily difficult.

  • ChrisChris

    Stephan,

    I agree for the most part. The non-deterministic nature of garbage collection with finalizers is significantly problematic in some cases

    The fact that in C++ you have to manage non-memory as well as memory resources with destructors (that is, with handle classes) brings us back to the problems that the relaxed sequencing ordering of C++ causes when passing temporaries managing resources to functions taking more than one argument. Your talk was a salutary reminder of this for me. I still feel queasy.

    Chris

  • Stephan,

    Great video. I am having a problem with uniform initialization. When I try to call an explicit constructor with uniform initialization, I get the following error.

     

    error C2440: 'initializing' : cannot convert from 'initializer-list' to 'S'

     

    Below is s small example

     

    
    struct S{
    
        explicit S(int){}
    
    };
    
    
    int main(){
    
        S s{10};
    }
    

     

    I originally got this error when using the brace initialization with ifstream which has a explicit constructor.

     

    The error resolves with either using parentheses instead of braces, or making the constructor not explicit.

     

    Is this a compiler bug, or is there something I am not understanding about uniform initialization

  • Xeoc9xeo Sanity is just a mask

    @jbandela: This particular case is a bug. The direct-list-initialization form ( T v{ ... }; ) should consider explicit constructors. Note that the copy-list-initialization form

    T v = { ... };
    foo({ ... })
    return { ... };
    

    does not.

  • STLSTL

    Chris> The fact that in C++ you have to manage non-memory as well as memory resources with destructors (that is, with handle classes) brings us back to the problems that the relaxed sequencing ordering of C++ causes when passing temporaries managing resources to functions taking more than one argument.

    It's actually not a problem, because temporaries are destroyed in the reverse order of their construction, whatever that order happened to be.

    jbandela, c9xeo: Yep, that's a bug. I filed it back on Nov. 3 as DevDiv#510870 "[Milan] list-initialization should be treated as direct-initialization".

  • Hey STL,

    Any Idea when User Defined Literals will be implemented in VC2012, i'm looking forward to trying something like,

    int operator "" _MB (unsigned long long) {return 1024;}
    
    int main(void)
    {
       int mySize = 34_MB;
    
      printf("%d",mySize);
      return 0;
    }

    Tom

  • STLSTL

    The future. Sorry, I'm not allowed to talk about release dates.

  • IvanIvan

    @STL
    great video, I only recently got some free time to you know sit down for an hour and focus so I have some late Q regarding the video.
    Your Sort example made me wonder:
    Is the accepted A on this SO Q wrong:
    http://stackoverflow.com/questions/11174501/why-no-sortv-in-c
    And 2 things regarding regarding VS11.
    1) You said that STL containers are now optimally small. Does that mean that standard prohibits a vector implementation that is just one ptr (end and capacity ptrs) are "prefixed" to data block, or just that you still consider the size of that vector to be 3*sizeof pointer.
    2) you mentioned in one comment somewhere (iirc) that you switched atomics to header only (from RC to RTM) for increased perf. Can you elaborate on that? If I remembered wrong just continue; without answering this question :)

  • STLSTL

    > Is the accepted A on this SO Q wrong:

    Kind of. In the absence of concepts, container-based algorithms could have been given different names. Consider random_shuffle(RanIt, RanIt, RNG&&) and shuffle(RanIt, RanIt, URNG&&).

    > You said that STL containers are now optimally small.

    I should have clarified (and did, in my original blog post) that this is "given their current representation".

    > Does that mean that standard prohibits a vector implementation that is just one ptr

    That's allowed, we just prefer not to do that.

    > you switched atomics to header only (from RC to RTM) for increased perf.

    That's correct.

    > Can you elaborate on that?

    Previously, <atomic>'s helper functions were separately compiled into msvcp110.dll/libcpmt.lib. This prevented inlining, which is important for things that are barely more expensive than plain increments. I performed massive surgery to move the helper functions, making them inline functions in our headers. Now they are full candidates for inlining, dramatically improving performance. We still have more performance work to do, but this part was important and necessary.

  • @STL:
    Thank you for a great series!

    I took the liberty of posting your implementation of make_unique and the examples from this video at http://scrupulousabstractions.tumblr.com/post/37576903218/cpp11style-no-new-delete , I hope that's fine, I found no printed version by you.

    I also wonder how this can be made easily available. You mentioned that you plan to propose this for the standard. I wonder if as a first step it could be added to boost? Are there any remaining concerns?   -- cheers, Johan

  • STLSTL

    I need to meditate on it some more. I'm not convinced that I've gotten the array form right (the scalar form is a trivial slam dunk).

  • Dear STL sorry for changing the subject, but I have question about exceptions.

    C++ standard $15.1 point 7 says: [If the exception handling mechanism, after completing evaluation of the expression to be thrown but before the exception is caught, calls a function that exits via an exception, std::terminate is called]

    seems g++ is ok with this point, while visual studio doesn't call std::terminate.

    I'm using VS-2012 evaluation version.

    Thanks in advance:)

  • STLSTL

    Works for me:

    C:\Temp>type meow.cpp
    #include <stdio.h>
    
    struct X {
        ~X() {
            puts("~X() is about to throw.");
            throw "EVIL";
        }
    };
    
    int main() {
        try {
            X x;
            puts("main() is about to throw.");
            throw 1729;
        } catch (...) {
            puts("We got to catch (...), but we should have terminated.");
        }
    
        puts("We got to the end of main(), but we should have terminated.");
    }
    
    C:\Temp>cl /EHsc /nologo /W4 /MTd meow.cpp
    meow.cpp
    
    C:\Temp>meow
    main() is about to throw.
    ~X() is about to throw.
    ---------------------------
    Microsoft Visual C++ Runtime Library
    ---------------------------
    Debug Error!
    
    Program: C:\Temp\meow.exe
    
    R6010 - abort() has been called
    
    (Press Retry to debug the application)
    
    ---------------------------
    Abort   Retry   Ignore
    ---------------------------
    

    VC doesn't terminate with the example in the Standard because of copy constructor elision.  Try putting a print statement in the copy constructor, and you'll see that it isn't getting invoked, so it doesn't get a chance to throw.

  • Thanks a lot @STL  Smiley

  • Dear @STL, 

    Thanks for your great job Cool .

    Merry Christmas and a very prosperous New Year to you!!! 

    Smiley

     

  • STLSTL

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

  • Nathan BinkertNathan Binkert

    STL: Any chance you can specify an open license (or better yet public domain) for the make_unique code in your talk? Also, did you do your meditation on the array form? Thanks!

  • Nathan BinkertNathan Binkert

    While playing with this, I was trying to figure out why you shouldn't allow the extent to be specified as long as the extent is at least as large as the number of arguments.

    // create unique_ptr to an array of 100 integers
    auto a = make_unique<int[100]>();

    // create a unique_ptr to an array of 100 integers and
    // set the first three elements to 1,2,3
    auto b = make_unique<int[100]>(1,2,3);


    Code here: https://github.com/binkert/make_unique/blob/master/make_unique.hh

  • HijokPayneHijokPayne

    I am relatively new to C++, and I really love your talks. It'll be great if you can talk more about static polymorphism in C++, or more common topics about templates in C++.

  • John HoriganJohn Horigan

    Thanks for moving <atomic> implementation into the <atomic> header. But I have a problem with being unable to include <atomic> from a C++/CLI file. I understand that CLR code cannot invoke <atomic> methods, but I have non-CLR C++ classes that have private members from <atomic>. My C++/CLI classes touch public members of these classes and invoke their public methods. I had to create a native-eyes-only derived class so that the headers visible to C++/CLI files did not include <atomic>. Can you relax the restriction on including <atomic> from C++/CLI and replace it with a restriction on interacting with atomics?

  • mloskotmloskot Mateusz Łoskot

    Stephan,

    Thanks for the very interesting lecture, quality as always.

    Quick question to explicit conversion operators and the bool.

    Has this feature been actually released?

    I'm using Visual Studio 2012 (Build 11.0.51106.01) and compilation of this trivial code:

    struct T{  explicit operator bool() const { return true; }};
    int main() {}

     

    throws error

    error C2071: 'T::operator bool' : illegal storage class

     

    Regards,

    Mat

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.