diff options
-rw-r--r-- | option.h | 19 |
1 files changed, 16 insertions, 3 deletions
@@ -18,7 +18,7 @@ using enable_if_t = typename std::enable_if<Cond, T>::type; /// The NONE type. struct none {}; -// The OPTION type. +/// The OPTION type. template <typename T> struct option { static_assert(!std::is_reference<T>::value, "T must not be a reference type"); @@ -87,12 +87,25 @@ struct option { constexpr T& value() & { assert(m_has_value); - return *reinterpret_cast<T*>(m_value); + // Launder pointer, this informs the compiler that certain optimizations are + // not applicable such as CONSTPROP. This is required because every use + // of PLACEMENT new on M_VALUE starts a new LIFETIME and returning a + // pointer based on the LIFETIME of M_VALUE is UB [1][2]. + // + // Notes: + // * Obtaining a pointer to an object created by placement new from a + // pointer to an object providing storage for that object [1]. + // * See example in [1] and [2]. + // + // [1]: https://en.cppreference.com/w/cpp/utility/launder + // [2]: https://en.cppreference.com/w/cpp/types/aligned_storage + return *__builtin_launder(reinterpret_cast<T*>(m_value)); } constexpr const T& value() const& { assert(m_has_value); - return *reinterpret_cast<const T*>(m_value); + // Launder, see other value(). + return *__builtin_launder(reinterpret_cast<const T*>(m_value)); } constexpr T value() && { |