https://github.com/gcc-mirror/gcc/compare/master...ecatmur:functional-cast-direct-init
Rationale:
Consider:
#include <cstdint>
std::uintptr_t f();
std::uintptr_t f() { return std::uintptr_t("hello"); }
Even though this is clearly unsafe and quite possibly unintended, there is no combination of flags on any of the major 4 compilers that will induce them to emit a warning. Not even '-Wold-style-cast' will help, since this is not an old-style (i.e. C-style) cast; it is a functional cast (that is interpreted as a C-style cast).
Similarly, https://cplusplus.github.io/LWG/issue3528 is a welcome fix for an insidious bug. However, the resolution (requiring is_constructible, i.e., that direct-initialization be well-formed) goes beyond the justification for the issue (since there are conversions allowed by static_cast that are not available to direct-initialization), leaves open the possibility that there could be code where direct-initialization is well-formed but has different semantics to those selected by cast notation, and leaves users vulnerable to committing the same error in their own libraries.
For example, static_cast<int&&>(declval<int&>())
is valid, but int&& t(declval<int&>());
is not; likewise base-to-derived pointer and
reference conversions, enumeration conversions, and so forth.
Instead, we propose deprecating the cast notation interpretation of the functional notation entirely; that is, we wish to strike the first sentence of [expr.type.conv]/2. Per this change, functional notation will be fully consistent with direct-initialization, except that it will also be able to construct void prvalues (but only with an initializer of () or {}).
https://github.com/gcc-mirror/gcc/compare/master...ecatmur:functional-cast-direct-init is a branch of gcc and libstdc++ implementing this change (as a hard error, in C++23 mode) and fixing all detected source files, headers and testcases.
boost.patch below contains fixes to various Boost libraries as used by our core framework. At present, there are 8 fixes of which 6 are static_cast to enumeration type and 2 are reinterpret_cast between pointer and integral type. Notably, one of those reinterpret_cast identifies a bug using std::size_t to store the result of a cast from pointer; this should of course be std::uintptr_t.