Now, the major concerns that some have is that this will not be successful, and that instead of replacing X with Y, you'll be left with both X and Y in the language as still necessary constructs for new code, making the language ever more complicated even if you can disregard the legacy.
C++ already suffers somewhat from the strong ties between many of its features (for example, many people would like to use C++ without exceptions, but then you can't use `new` or constructors that can fail, and without constructors you can't use RAII, and so on).
For instance, `new` is basically nothing short of obsolete in modern C++, unless when used in "placement new". There are legally 0 reasons for ever writing `new T`, unless you are implementing `std::make_unique()` in the STL. Disabling exceptions is also IMHO a very poor choice - first, because there is no valid performance reason to do so, and second because it basically cripples half of the STL (and lots of other libraries). Using it becomes then tricky to use safely, because basically everything might just call std:: terminate () anywhere without any formal specification, or without being declared `noexcept`, by just changing compiler options.
C++ exceptions, when used sparingly and for, well, exceptional events, are not as bad as people think they are. What's very unfortunate is that they got a very bad rap in the 90s, and then countless developers have been mislead by Java's unfortunate design choices, so they often fail to understand that handling failures should always considered part of the ordinary code path, and not treated as exceptional at all.
I personally use exceptions as if they are a lighter version of assert, like `panic` from Rust or Go, in order to indicate that some basic code assumption has been violated, and thus executing a certain action is no longer possible (like, some parameter is malformed and you specifically asserted it's not, and such). Using them to represent normal runtime failures, such as IO errors, is sloppy design, and it's something that is much better accomplished by returning error values (which might also consist in enum classes or an error struct).
> but then you can't use `new`
You can certainly use new without exceptions, see https://en.cppreference.com/w/cpp/memory/new/nothrow or https://stackoverflow.com/a/15292148
> and without constructors you can't use RAII, and so on).
I think RAII is more about destructors (which must never throw exceptions). You can certainly write RAII style without throwing constructors. Generally, exceptions depend on RAII, but not the other way round.
You can use new without exceptions, but you can't detect OOM then, if I'm not mistaken.
> I think RAII is more about destructors (which must never throw exceptions). You can certainly write RAII style without throwing constructors. Generally, exceptions depend on RAII, but not the other way round.
The whole idea of RAiI is that you Acquire a Resource in the constructor (during Initialization), so that the destructor can guarantee it gets de-allocated.
If you construct your object and then acquire a resource in it later, from a function that can return an error without throwing, then you introduce complexity in the destructor and may risk errors more.
Yes, that's the meaning of the acronym means, but unfortunately it's really a misnomer.
When we say RAII style programming, we rather mean scoped destruction to avoid manual resource management. A classic example would be using std::lock_guard over a raw std::mutex. Some RAII objects don't throw on resource acquisition failure (std::fstream) or they expect that resource acquisition can fail (std::unique_lock with std::try_to_lock tag). Other RAII objects might not require any resource in the constructor at al, instead their only job is to release the resource that is given to them, like std::unique_ptr.
AFAIK `new (std::nothrow) T` returns nullptr if allocation fails, like std::malloc.
You can detect the same errors with and without exceptions - the nothrow variant returns nullptr on error. Due to overcommit, neither can be relied on to detect OOM in practice.
> If you construct your object and then acquire a resource in it later, from a function that can return an error without throwing, then you introduce complexity in the destructor and may risk errors more.
Not neccessrily, e.g. free and delete are both no-ops for nullptr.
C++20 with concepts and ranges will revolutionise everything, again, because those features are so big and pervasive they make lots of patterns and "older" parts f the language suddenly feel like "legacy". For instance, I see concepts vastly reducing the need for inheritance in lots of cases, massively simplifying what lots of folks like me were already doing with SFINAE and templates.