C++ has made a point of pride to thoroughly keep backward compatibility so that even the most antique and obsolete C++ source code may compile with just a few warnings (if any). This may be good to someone, but it makes for some funny constructs. E.g.:
[[nodiscard]] bool isEmpty() const override noexcept;
[[nodiscard]] means that the value returned by the function is not to be ignored (well you will get just a warning, so it is still
override means that this function overrides a virtual function in the base class. Nothing wrong with that, but… why “override” has to be placed past the argument list where its visibility is minimal? Because in the committee they didn’t feel right to add a new keyword to the language (actually two keywords –
final) fearing to break compatibility. So they invented that after the function argument list the language accepts an identifier (yes, any symbol-like identifier) and then it gets interpreted during compilation to report an error in case it is neither,
noexcept marks the function as not throwing exceptions. Again a reasonable take would be to have the programmer mark function that can throw exceptions since those functions are problematic and have to be handled with care. It should be just the norm that a function does not throw. Yes, I
Not to mention the use of explicit keyword for constructors –
explicit Constructor( T const& ) noexcept;
Just to recap – as the language was designed at the beginning – if a constructor has just one argument (or one argument without default values) that constructor is used by the compiler to implicitly convert from the type of the argument to the type of the class.
That is if a type of
This is sometimes a nice tool, but unintended use could cause some trouble possibly in a subtle way. In the first language revision (C++11) the explicit keyword was added to let the programmer select if she wants implicit or explicit construction. Since the problems are with implicit conversion, it would have made much more sense that the programmer had to express her intent to pick the most dangerous option, not the safer one.
(BTW, I just discovered that C++20 adds another use case
And talking about