The background for these is at https://stackoverflow.com/questions/40983822/cannot-use-a-constant-reference-of-experimentaloptional-when-using-clang-lib
We use excessive trickery to constrain __constexpr_addressof in experimental::optional. That trickery is not agreed on by compilers, and we can cope with a much simpler approach. The first patch just simplifies that trickery by moving the constraints from a template parameter to the return type. The second patch uses a constexpr std::__addressof if it's available. I split these out in case we want just the first patch but not the second. The second patch allows C++17 users to benefit from a completely constexpr addressof even for experimental::optional (std::optional already gives that). Tested on Linux-x64. Ok for trunk, the gcc-6 branch and the gcc-5 branch? 2016-12-06 Ville Voutilainen <ville.voutilai...@gmail.com> Constrain optional's __constexpr_addressof in its return type. * include/experimental/optional (__constexpr_addressof): Constrain in the return type instead of in a template parameter. 2016-12-06 Ville Voutilainen <ville.voutilai...@gmail.com> Use a constexpr addressof for optional, if available. * include/experimental/optional (_Has_addressof_mem) (_Has_addressof_free, _Has_addressof, __constexpr_addressof): Guard with #ifndef __cpp_lib_addressof_constexpr. (operator->()): Use std::__addressof if it's constexpr.
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional index a631158..8263639 100644 --- a/libstdc++-v3/include/experimental/optional +++ b/libstdc++-v3/include/experimental/optional @@ -170,15 +170,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION * overloaded addressof operator (unary operator&), in which case the call * will not be a constant expression. */ - template<typename _Tp, enable_if_t<!_Has_addressof<_Tp>::value, int>...> - constexpr _Tp* __constexpr_addressof(_Tp& __t) + template<typename _Tp> + constexpr + enable_if_t<!_Has_addressof<_Tp>::value, _Tp*> + __constexpr_addressof(_Tp& __t) { return &__t; } /** * @brief Fallback overload that defers to __addressof. */ - template<typename _Tp, enable_if_t<_Has_addressof<_Tp>::value, int>...> - inline _Tp* __constexpr_addressof(_Tp& __t) + template<typename _Tp> + inline + enable_if_t<_Has_addressof<_Tp>::value, _Tp*> + __constexpr_addressof(_Tp& __t) { return std::__addressof(__t); } /**
diff --git a/libstdc++-v3/include/experimental/optional b/libstdc++-v3/include/experimental/optional index 8263639..6994e77 100644 --- a/libstdc++-v3/include/experimental/optional +++ b/libstdc++-v3/include/experimental/optional @@ -134,6 +134,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION __throw_bad_optional_access(const char* __s) { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); } +#ifndef __cpp_lib_addressof_constexpr template<typename _Tp, typename = void> struct _Has_addressof_mem : std::false_type { }; @@ -184,6 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION enable_if_t<_Has_addressof<_Tp>::value, _Tp*> __constexpr_addressof(_Tp& __t) { return std::__addressof(__t); } +#endif // __cpp_lib_addressof_constexpr /** * @brief Class template that holds the necessary state for @ref optional @@ -709,7 +711,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // [X.Y.4.5] Observers. constexpr const _Tp* operator->() const - { return __constexpr_addressof(this->_M_get()); } + { +#ifndef __cpp_lib_addressof_constexpr + return __constexpr_addressof(this->_M_get()); +#else + return std::__addressof(this->_M_get()); +#endif + } _Tp* operator->()