As software using c++17 is upon us, we have a slight problem with std::optional.
clang has supported std::optional for some time, and clang-9.0, at least,
appears to support std::optional right back to the ancient systems.
however, there is one small part of std::optional, std::optional::value, that
needs a callback function in case of an exception being thrown, called
“bad_optional_access”. That symbol is compiled into libc++.dylib as of 10.13.
So clang-9.0 supports 99% of std::optional all the way back, but that
bad_optional_access function limits that one part of it, std::optional::value,
to 10.13.
There are availability tests build into the libc++ headers based on system
version to turn that off.
However, on 10.6, where I build and install libc++ 5.0, that symbol exists in
libc++.dylib, so I disable clang’s availability tests.
It is quite simple (I think) to inline a function implementing
bad_optional_access into the <optional> header. That could be used for 10.7 to
10.12, and then all those systems could comfortably implement c++17, and no
problem. Otherwise we have to install a newer libc++.dylib on older systems,
which is a simple but big problem, as it were.
Here’s the <optional> patch. I only speak basic c++, so improve this if you can.
So I am proposing to use this patch, and disable Apple’s availability test in
<__config> for bad_optional_access.
Then all systems from 10.5 to current can use c++17 std::optional, and disaster
averted until the next crisis.
Warts?
Ken
<optional> patch:
$ diff -u optional.orig optional
--- optional.orig 2020-07-04 18:51:05.000000000 -0700
+++ optional 2020-07-04 18:51:13.000000000 -0700
@@ -168,13 +168,10 @@
namespace std // purposefully not using versioning namespace
{
-class _LIBCPP_EXCEPTION_ABI _LIBCPP_AVAILABILITY_BAD_OPTIONAL_ACCESS
bad_optional_access
- : public exception
-{
+// 20.5.8, class bad_optional_access
+class bad_optional_access : public logic_error {
public:
- // Get the key function ~bad_optional_access() into the dylib
- virtual ~bad_optional_access() _NOEXCEPT;
- virtual const char* what() const _NOEXCEPT;
+ explicit bad_optional_access() : logic_error{"bad optional access"} {}
};
} // std