Interview: On simplifying C++

I was also interviewed recently by Anastasia Kazakova for the CLion blog, and that interview is now live:

Toward a more powerful and simpler C++ with Herb Sutter

Topics include:

  • Concepts and modules (and coroutines) as the true hot topics right now
  • How my work on metaclasses was motivated and developed
  • Obligatory aside on operator<=> which grew out of the same work
  • Good and bad ways to learn from other languages and their experience
  • What are the next questions to be answered for metaclasses proposal
  • What has been the committee’s feedback so far
  • How can we expect to see reflection, compile-time code, injection, and metaclasses both progress in committee and get built into production compilers
  • How toolable are today’s C++11/14/17 features, and what about toolability for metaclasses

4 thoughts on “Interview: On simplifying C++

  1. Thanks for providing the chance to share my ideas with the rest of the world.
    So! There are some of my notes to share with the rest of the world:

    1. The idea of making something more simple, if the word simple is used in usual manner is iffy … There is very good example of Java and overloading operators. In some cases we will end up with some very long long expressions and the is not the only case. However, there are some really nice stuff about Java, the way the matrix could be used, in particular, well dynamic one.

    2. The idea of templates is great, though there should be more work be done. Because, there are some more things that need to be implemented. One could be found in matheval.h, that is part of GNU project and it will allow the programmer to have more power and flexibility at the same time. That would in a way let us create the “functions” body in more power full way.

    3. Idea of providing some things like delegates, could be accomplished with pointers to the functions, but if somebody is pleased …

    4. The part in which we try to define the error it is important too. This way it has a lot of freedom, but if one could take the shot of the registers etc… and send the report to the developer, that would be more useful. Well, I guess.

    5. The next thing the multi threading is done in not so smart way… and the outcome is not that good.

    6. Having virtual part inside the class and let’s say friend and then private, protected and public would change mush of the hurdles we face each and every day…

  2. Hello Mr. Sutter,

    I read your interview with great interest since I am a long time C++ developer and I am interested in all new cool features that would help improve my work efficiency and code style. In particular, I liked very much your idea of examining pieces of code and extracting snippets from them, in order to pursue new avenues of improvements.

    As a long practitioner of C++ developer, I also have some suggestions that have accumulated during the years. They might not seem important, but I find these scenarios over and over again, and smallest improvements are more than welcome.

    So, here they are:
    1. The {code}while(true){/code} problem. While most people are used of of writing this, there are some issues: usually the compiler will trigger an infinite loop warning (MS), or, if if replace it with {code}(while(some_condition){/code}, doesn’t really express intent if there can be multiple exit points.
    One example would be a merge sort:

    void merge(Node* list1, Node* list2)
    {
        while (list1)
        {
            if (list2 == nullptr) break;
            ...
            list1 = list1->next;
            continue;
            ...
            list2 = list1->next;
            continue;
        }
    }
    

    I understand that this code is not very often found in a C++ world, but I used it as an example
    My proposal would be a plain C keyword loop{} which can be break-able and continue-able (break and continue work the same as in a while-loop), or, as a C++ extension, the

    std::loop(void<void>)

    .
    This approach has the disadvantage that is non-trivially continue-able.

    2. An artificial scope. I understand that most of the time it is recommended to create a new method, but there are lots of cases where for simplicity, an artificial scope is helpfull.
    Considering a class {code}std::scope(void scopeWork){/code}, the you could use simple methods like the following:

    void SomeFunction(...)
    {
        ... do some work
        std::scope([myMutex](){
            std::lock_guard<std::mutex> lock(myMutex);
            //perform safe work
        });
        
        // perform some other work.  
    }
    

    3. A scope cleanup way. This would be something like a scope destructor, instead of extending a class’s destructor with extra functionality, you can have a static constructor.
    There would be 2 ways to achieve this: custom class ({code}std::on_scope(void scopeFunction{/code})or extending std::scope ({code}std::scope(void scopeWork, void scopeCleanup){/code})

    void SomeFunction(...)
    {
        std::on_scope([](){PerformLegacyCleanup();});
        auto logger = GetLogger();
        std::on_scope([logger](){logger->LogSomething();});
        
        std::scope([](){
            PerformWork();
        });
    }
    

    or

    void SomeFunction(...)
    {   
        auto logger = GetLogger();
        
        std::scope([](){
            PerformWork();
            if(condition)
                return;
            PerformOtherWork();
        },
        [logger](){
            logger->LogSomething();
            PerformLegacyCleanup(); // order is reversed
        });
    }
    

    I understand that many of the C++ comittee are geared towards making C++ a pure language and cut as much of the C roots, but the reality is, that there is a lot of legacy code out there, that we have to work with, and, I would say, these proposals also help people write better C++ code.

    4. Process/Module scope variables
    At the moment, the C/C++ language doesn’t guarantee scope of the variables, and many times, we, as developers, must create all kinds of workaround to achive this in a platform specific way.
    The problem I see is that when C/C++ was designed, only the concept of static linking was present, and from what I see, this hasn’t changed (I might be wrong here, please correct me I am).
    For example, let’s suppose have in a static library:

    //singleton.h
    int* GetSingleton();
    //singleton.cpp
    static int singleton = 0;
    int* GetSingleton()
    {
        return &singleton;
    }
    

    If I include this library in 2 different dlls, which will then be included into one preocess, then I will have the variable singleton instantiated twice:

    0:000> x *!singleton
    0f858000          dll2!singleton = 0n5
    0ffa8000          dll1!singleton = 0n5
    

    My proposal would be to have 2 new keywords or classes, to allow developers to specify 2 scopes: module_scope and process_scope. A typical usage would be:

    void DllA!Function1()
    {
        std::process_scope<T> ps("unique_name");
        ps.some_data = 5;
        std::module_scope<T> ms("unique_name");
        ps.some_data = 10;
    }
    void DllB!Function2()
    {
        std::process_scope<T> ps("unique_name");
        Assert(5 == ps.some_data);
        std::module_scope<T> ms("unique_name");
        Assert(10 != ms.some_data);
    }
    

    I know that this is not a trivial task to ask, because of the timing problems:
    – when should a module_scope variable be initialized? what about destroyed? My proposal is to initialize when it’s first used and destroyed when module is unload, after static variables.
    – when should a process_scope variable be initialized? what about destroyed? My proposal is to initialize when it’s first used, and destroyed after all module_scope variables were destroyed (from all modules).

  3. 1. You can generally use

    for(;;)

    instead of

    while(true)

    to get rid of the warning.
    2. The code you propose

        std::scope([myMutex](){
            std::lock_guard<std::mutex> lock(myMutex);
            //perform safe work
        });
    

    can already be written as

        {
            std::lock_guard<std::mutex> lock(myMutex);
            //perform safe work
        }
    
  4. Hello,
    apparently pretty exciting things are coming to C++. Thanks for all this work.

    I wonder how far this functionality metaclasses is actually far from static reflection as
    iterating fields and methods decomposing them and based on that adding new code to classes is pretty close.

    If there is much overlap between those two (metaclasses and static reflection) wouldn’t there is a case for a unified approach for the two.

    Maciej Jablonski

Comments are closed.