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

C++ and Beyond 2012: Herb Sutter - You don't know [blank] and [blank]

Download

Right click “Save as…”

Herb Sutter presents a "startling realization he had about C++11", and he thinks it may be a bit startling for others too. Tune in.

This was filmed at C++ and Beyond 2012

Download Herb's slides for this session.

Abstract:

In addition to the many new C++11 features that everyone's listing, it has dawned on me over the winter that there's actually another major change that isn't being talked about anywhere, or even being listed as a change in C++11 at all as far as I know, because I and other key experts and committee members I've asked didn't fully realize that we altered the basic meaning of not one but two fundamental keywords in C++. It's a change that has profound consequences, that rewrites and/or invalidates several pieces of pre-C++11 design guidance, and that's directly related to writing solid code in a concurrent and parallel world. This isn't just an academic change, either — everyone is going to have to learn and apply the new C++11 guidance that we'll cover in this session.

I plan to talk about it first at C&B, in a session tentatively titled as above — I'll fill in the keywords later. You may already guess a few keyword candidates based on the description above, and here's a final hint: You'll hardly find two C++ keywords that are older, or whose meanings are more changed from C++98 to C++11. (No, they aren't auto and register.)

Tags:

Follow the Discussion

  • does c++11 provide yield return and extension methods as we know them from C#?  Does it do away with header files?

     

  • felix9felix9 the cat that walked by itself

    Thanks Smiley

  • Christian SemmlerChristian Semmler

    Sweet! Thanks a lot for sharing.

  • Roman PerepelitsaRoman Perepelitsa

    Applying const_cast to class members can cause undefined if the object itself was defined as const. Mutable doesn't have this problem.

    struct Foo {
    int value;
    void Mutate() const {
    const_cast<int&>(value) = 42;
    }
    };

    struct Bar {
    mutable int value;
    void Mutate() const {
    value = 42;
    }
    };

    const Foo foo = {};
    const Bar bar = {};

    int main() {
    foo.Mutate(); // Undefined Behavior.
    bar.Mutate(); // OK.
    }

  • Ah the perfect end to 2012! This has been the best year for native code at Microsoft in well over a decade. Going into 2013 please keep up the investment in native, there has been much ground lost in both market and mindshare over the past ~12 years, but I passionately believe you guys can turn this around. Deliver the RTM parts previewed in the VC++ November CTP and you're well on your way to having IMO the best C++ 11 dev experience out there.

  • CharlesCharles Welcome Change
    @dot_tom: We're not letting up!! C
  • Why is const needed anyway?  C# does not have the concept.

    Another C++ request ...  enum class.  Have a built in ToString method or enable enum class to have member functions, or add extension methods to the language.  The purpose being to enable enum specific code, like Parse and ToString, to be called using dot notation from an enum instance.

    enum class Colors { red, white, blue } ;
    Colors color = Colors::red ;
    auto textColorName = color.ToString( )
    auto anotherColor = Colors::Parse( textColorName ) ;

    Bigger picture. Give me a native version of C#. Or enhance the struct handling capabilites of C#. ( C# cannot efficiently handle PIDLs used by windows shell. ) Microsoft to this day says that windows shell code written in C# is unsupported. A C# like native code language would be awesome.

     

  • TianyuTianyu

    Steve, the whole point of C++ is to give you the tools to make such a class. Perhaps you can come up with an implementation and propose it as part of the standard STL?

  • Well, that's an interesting insight. It's going to take me a moment to wrap my head around this Smiley. I keep coming up with ways to invalidate it, but then go "oh, no, it still holds..."

  • petkepetke

    Maybe a silly question. But, if mutable == const (== thread-safe)

    Shouldn't the following mean the same?

    mutable std::mutex<int> m1;
    const std::mutex<int> m2;

    If not, why?

  • turck3turck3

    @petke - I believe the difference is in how you state intent to the compiler.

    When you have a const object, you're telling the compiler to forbid use of all non-const functions; the compiler can, in that manner, enforce the const/thread-safe guarantees that the class writer gave you.

    When you call something mutable under the new definition, you're stating 'I trust the author of this type to have made it entirely synchronized/thread-safe'. The compiler will then not restrict what methods you can call.

    I would argue that mutable is a keyword indicating your trust in the author, whereas const is about the author providing compiler-enforceable guarantees for the user.

    Code example:
    struct myStruct {
    const mutex m1;
    mutable mutex m2;

    void f1() const { m1.lock(); } //COMPILE-TIME ERROR
    void f2() const { m2.lock(); }
    };

    int main() {
    const myStruct x;
    x.f2(); //OK - author claims that myStruct is internally synchronized

    return 0;
    }

  • petkepetke

    @turck3 Thanks. I still have an uneasy feeling about the new definition. If const is thread-safe. Why isn't the method std::mutex::lock defined as const (as its internally synchronized)?

  • XTFXTF

    I think Herb is wrong. Const implies thread-safe, but thread-safe does not imply const, so the two are not equal/equivalent.

    Concurrent containers etc will certainly be thread-safe but not all functions will be const.

  • Arkadiy BelousovArkadiy Belousov

    Doesn't this mean that "mutable" is an attribute of class rather than attribute of class' usage? In other words, we may be better off saying

    mutable class Mutex{/*...*/};

    rather than

    class A {
    mutable Mutex m;
    };


    ?

  • Steve, the whole point of C++ is to give you the tools to make such a class.

     

    but in practice Tianyu, you end up getting some inscrutable compile errors.

    Find the error in this code.  Note the bullshit compile error.

      void Tester2( unique_ptr<std::wstring> pString )  {  }  void CallTester2( )  {    unique_ptr<std::wstring> pString ;    Tester2( pString ) ;  }

     

     4 IntelliSense: "std::unique_ptr<_Ty, _Dx>::unique_ptr(const std::unique_ptr<_Ty, _Dx>::_Myt &) [with _Ty=std::wstring, _Dx=std::default_delete<std::wstring>]" (declared at line 1447 of "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\memory") is inaccessible c:\SkyDrive\democpp\Tester\Tester.cpp 379 14 Tester
    Error 3 error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>' c:\skydrive\democpp\tester\tester.cpp 382 1 Tester

  • snkkidsnkkid

    @PhrostByte it is very easy to invalidate this, constant member functions do not enforce referentially transparency (pure functions) even in C++11. You can still modify global or (class) static unsynchronized variables in constant member functions or modify unsynchronized data members marked as mutable.

    You can say this is a bug/undefined behavior (in the context of concurrent/parallel code) but this is an issue with the language/library if the standard say that constant member functions must be side-effect free but the language does not enforce this thus the compiler will never enforce this.

    From my point of view const does not guarantee thread safety, this is only a promise that can be silently broken. This is not particular useful.

    This change in C++11 is actually a breaking but silent change to existing code and you have no help from the language/compiler to find and fix any buggy code which is not C++11 compliant.

  • @SteveRichter: Clang gives a more readable diagnostic message:

    source.cpp:6:79: error: call to deleted constructor of 'std::unique_ptr<std::wstring>'
    void CallTester2( ) { std::unique_ptr<std::wstring> pString ; Tester2( pString ) ; }
                                                                         ^~~~~~~
    note: function has been explicitly marked deleted here unique_ptr(const unique_ptr&) = delete;
    

    See: http://liveworkspace.org/code/1zPqd0$1

    In other words, copy constructor is deleted -- in other words, unique_ptr is non-copyable.

    BTW, regarding enums, you can always implement something like this: http://www.ishani.org/web/2012/fancy-c-enums/

  • GaryGary

    Thanks Herb! Great lecture and explanation. Looking forward to the rest of the lectures as they get released.

  • @PhrostByte it is very easy to invalidate this, constant member functions do not enforce referentially transparency (pure functions) even in C++11. You can still modify global or (class) static unsynchronized variables in constant member functions or modify unsynchronized data members marked as mutable.

    You can say this is a bug/undefined behavior (in the context of concurrent/parallel code) but this is an issue with the language/library if the standard say that constant member functions must be side-effect free but the language does not enforce this thus the compiler will never enforce this.

    From my point of view const does not guarantee thread safety, this is only a promise that can be silently broken. This is not particular useful.

    This change in C++11 is actually a breaking but silent change to existing code and you have no help from the language/compiler to find and fix any buggy code which is not C++11 compliant.

    In other words, it's no different from most everything else in C++ -- helping you a good deal but still not "enforcing" anything, allowing you to do whatever the hell you want in the end Smiley

    A compiler may not be able to catch and warn about all instances of broken code (you're right, this is a breaking change), but there's a lot of room here for it to help.

  • Thanks!

  • Anonymous CowardAnonymous Coward

    Apparently I'm confused. I always though "const" meant "immutable"; now Herb is telling us that "const" means "mutable"? Wha..? Do an American English dictionary search for "mutable", por favor...

  • CharlesCharles Welcome Change

    @Anonymous Coward: Watch and actually listen to what Herb says...
    C

  • Andre OffringaAndre Offringa

    Very interesting talk! Thanks a lot for sharing it.

    I would think that saying that both mutable and const *imply* thread safe is better than stating they equal thread safe. After all, const also implies "not allowed to perform non-const operations on" while mutable implies the opposite, so mutable != const. But that's just a nitpicking comment ;). The presentation is very insightful.

  • kipkip

    Thanks for this excellent talk, Herb !

    I have a question though. This mutable mutex story seems kind ow awkward to me.

    You said that "const" now means "thread-safe", and that "mutable" means "known to be thread-safe". If the mutex is thread-safe, as you said in your talk, shouldn't all its methods be declared const ? Therefore, the mutex would not have to be declared mutable.

  • Alessandro StamattoAlessandro Stamatto

    @Kip : When you say a thing is a const you're saying "Look, think of this as immutable / assume I will not modify it" and for most cases it will be immutable/you will not modify. BUT if you modify it you have to guarantee that you will not mess concurrency/synchronization.

    And, in most cases, the compiler will not let you directly break your promise of immutable/non-modify. For that you have to explicitly cast the const thing to a non-const thing. OR you can say that thing is in fact mutable.

    Now when you say something is mutable you're saying "Look, this is not immutable but I guarantee that it will not cause problems with concurrency/synchronization, it's already synchronized"

    Const -> it's immutable, and as such thread-safe.
    Mutable -> it's mutable, but let me use as immutable because I guarantee it's thread-safe.

  • Andreas PfaffenbichlerAndreas ​Pfaffenbich​ler

    hi herb!

    for me the point in this 'const/mutable' talk is, that you missed in your introducion a 'const':

    #include <utility>
    #include <future>
    #include <vector>
    using namespace std;
    /**/const/**/ vector<int> v(1000); // <--
    int main() {
    auto x = async([/**/&/**/]{ pair<int,vector<int>> z{ 1, v }; });
    auto y = async([/**/&/**/]{ pair<int,vector<int>> z{ 2, v }; });
    x.wait(); y.wait();
    }

    without this /**/const/**/, you have to 'know' that nobody modifies 'v'.

    am i right?

    best regards
    andreas pfaffenbichler

  • Kip CoulKip Coul

    @Alessandro,

    Thanks for your answer, Alessandro. However, I can't say I fully agree, though I understand your point.

    The conclusion of what you said is "Const -> it's immutable, and as such thread-safe."
    This is precisely what puzzles me. Since a mutex is inherently thread-safe (thanks to some *internal* mechanism), why doesn't it expose its constness to the outside world ?
    I think that the stl standard breaks the encapsulation rule here.
    Basically, when you say that the lock method of a mutex is non-const, you're saying:
    "OK, by some internal mechanism, I have to modify some private variables of the mutex, in order to make it thread-safe, therefore it is non-const". Basically, you're exposing the internal working of the mutex by saying its lock method is non const, though it's thread safe.

    I hope I am clear in my explanation. Feel free to send me an email to further discuss this point (first-name dot last-name at gmail.com)

  • Erik WErik W

    @Kip Coul

    I think the point is that const is not the same as thread safe. const implies thread safe, but thread safe does not imply const.

    The mutex is not const, and in fact that is what allows it to synchronize, if the mutex is not locked you need to lock it to synchronize, but you can't change the state of the mutex if it is const (despite of what Herb might have said, const still means immutable).

    That's where mutable comes in, because mutable (just like const) implies thread safe. But while const implies it since something that can't change by definition is thread safe, mutable is thread safe since you do you some form of synchronization.

    I think the key to understanding is the fact that thread safe != const, you can use other means of synchronization (for example a mutex). And if your class is not const then the mutex is not const either, so if the mutex's functions are non-const that's OK.

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.