[v3 PATCH] Use constexpr addressof in optional, SFINAE housekeeping for any, optional and tuple.

Ville Voutilainen ville.voutilainen@gmail.com
Wed Oct 26 17:10:00 GMT 2016


Tested on Linux-PPC64.

2016-10-26  Ville Voutilainen  <ville.voutilainen@gmail.com>

    Use constexpr addressof in optional, SFINAE housekeeping
    for any, optional and tuple.
    * include/std/any (__do_emplace(_Args&&...)): New.
    (__do_emplace(initializer_list<_Up>, _Args&&...)): Likewise.
    (__any_constructible): Likewise.
    (__any_constructible_t): Use __any_constructible.
    (operator=(_ValueType&&)): SFINAE in the return type.
    (emplace(_Args&&...)): Likewise.
    (emplace(initializer_list<_Up>, _Args&&...)): Likewise.
    * include/std/optional (_Has_addressof_mem): Remove.
    (_Has_addressof_free): Likewise.
    (_Has_addressof): Likewise.
    (__constexpr_addressof(_Tp&)): Likewise.
    (operator->): Use std::__addressof.
    * include/std/tuple (operator=(const tuple<_UElements...>&)):
    SFINAE in return type.
    (operator=(tuple<_UElements...>&&)): Likewise.
    * testsuite/20_util/any/misc/any_cast_neg.cc: Adjust.
-------------- next part --------------
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 45a2145..719e683 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -108,6 +108,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     template<typename _Tp, typename _Decayed = decay_t<_Tp>>
       using _Decay = enable_if_t<!is_same<_Decayed, any>::value, _Decayed>;
 
+    /// Emplace with an object created from @p __args as the contained object.
+    template <typename _Tp, typename... _Args,
+	      typename _Mgr = _Manager<_Tp>>
+      void __do_emplace(_Args&&... __args)
+      {
+	reset();
+	_M_manager = &_Mgr::_S_manage;
+        _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+      }
+
+    /// Emplace with an object created from @p __il and @p __args as
+    /// the contained object.
+    template <typename _Tp, typename _Up, typename... _Args,
+	      typename _Mgr = _Manager<_Tp>>
+      void __do_emplace(initializer_list<_Up> __il, _Args&&... __args)
+      {
+	reset();
+	_M_manager = &_Mgr::_S_manage;
+        _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+      }
+
   public:
     // construct/destruct
 
@@ -144,11 +165,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	}
     }
 
+    template <typename _Res, typename _Tp, typename... _Args>
+    using __any_constructible =
+      enable_if<__and_<is_copy_constructible<_Tp>,
+			 is_constructible<_Tp, _Args...>>::value,
+		  _Res>;
+
     template <typename _Tp, typename... _Args>
     using __any_constructible_t =
-      enable_if_t<__and_<is_copy_constructible<_Tp>,
-			 is_constructible<_Tp, _Args...>>::value,
-		  bool>;
+      typename __any_constructible<bool, _Tp, _Args...>::type;
 
     /// Construct with a copy of @p __value as the contained object.
     template <typename _ValueType, typename _Tp = _Decay<_ValueType>,
@@ -233,9 +258,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
     /// Store a copy of @p __rhs as the contained object.
-    template<typename _ValueType,
-	     typename _Tp = _Decay<_ValueType>>
-      enable_if_t<is_copy_constructible<_Tp>::value, any&>
+    template<typename _ValueType>
+      enable_if_t<is_copy_constructible<_Decay<_ValueType>>::value, any&>
       operator=(_ValueType&& __rhs)
       {
 	*this = any(std::forward<_ValueType>(__rhs));
@@ -243,29 +267,26 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
 
     /// Emplace with an object created from @p __args as the contained object.
-    template <typename _ValueType, typename... _Args,
-	      typename _Tp = _Decay<_ValueType>,
-	      typename _Mgr = _Manager<_Tp>,
-              __any_constructible_t<_Tp, _Args&&...> = false>
-      void emplace(_Args&&... __args)
+    template <typename _ValueType, typename... _Args>
+      typename __any_constructible<void,
+				   _Decay<_ValueType>, _Args&&...>::type
+      emplace(_Args&&... __args)
       {
-	reset();
-	_M_manager = &_Mgr::_S_manage;
-        _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...);
+	__do_emplace<_Decay<_ValueType>>
+	  (std::forward<_Args>(__args)...);
       }
 
     /// Emplace with an object created from @p __il and @p __args as
     /// the contained object.
-    template <typename _ValueType, typename _Up, typename... _Args,
-	      typename _Tp = _Decay<_ValueType>,
-	      typename _Mgr = _Manager<_Tp>,
-              __any_constructible_t<_Tp, initializer_list<_Up>,
-				    _Args&&...> = false>
-      void emplace(initializer_list<_Up> __il, _Args&&... __args)
+    template <typename _ValueType, typename _Up, typename... _Args>
+      typename __any_constructible<void,
+				   _Decay<_ValueType>,
+				   initializer_list<_Up>,
+				   _Args&&...>::type
+      emplace(initializer_list<_Up> __il, _Args&&... __args)
       {
-	reset();
-	_M_manager = &_Mgr::_S_manage;
-        _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...);
+	__do_emplace<_Decay<_ValueType>, _Up>
+	  (__il, std::forward<_Args>(__args)...);
       }
 
     // modifiers
diff --git a/libstdc++-v3/include/std/optional b/libstdc++-v3/include/std/optional
index f272876..35b6932 100644
--- a/libstdc++-v3/include/std/optional
+++ b/libstdc++-v3/include/std/optional
@@ -96,53 +96,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __throw_bad_optional_access(const char* __s)
   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
 
-  template<typename _Tp, typename = void>
-    struct _Has_addressof_mem : std::false_type { };
-
-  template<typename _Tp>
-    struct _Has_addressof_mem<_Tp,
-         __void_t<decltype( std::declval<const _Tp&>().operator&() )>
-      >
-    : std::true_type { };
-
-  template<typename _Tp, typename = void>
-    struct _Has_addressof_free : std::false_type { };
-
-  template<typename _Tp>
-    struct _Has_addressof_free<_Tp,
-         __void_t<decltype( operator&(std::declval<const _Tp&>()) )>
-      >
-    : std::true_type { };
-
-  /**
-    * @brief Trait that detects the presence of an overloaded unary operator&.
-    *
-    * Practically speaking this detects the presence of such an operator when
-    * called on a const-qualified lvalue (e.g.
-    * declval<const _Tp&>().operator&()).
-    */
-  template<typename _Tp>
-    struct _Has_addressof
-    : std::__or_<_Has_addressof_mem<_Tp>, _Has_addressof_free<_Tp>>::type
-    { };
-
-  /**
-    * @brief An overload that attempts to take the address of an lvalue as a
-    * constant expression. Falls back to __addressof in the presence of an
-    * 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)
-    { 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)
-    { return std::__addressof(__t); }
-
   /**
     * @brief Class template that holds the necessary state for @ref optional
     * and that has the responsibility for construction and the special members.
@@ -681,7 +634,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       // Observers.
       constexpr const _Tp*
       operator->() const
-      { return __constexpr_addressof(this->_M_get()); }
+      { return std::__addressof(this->_M_get()); }
 
       _Tp*
       operator->()
diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple
index c06a040..63cacd4 100644
--- a/libstdc++-v3/include/std/tuple
+++ b/libstdc++-v3/include/std/tuple
@@ -846,20 +846,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	return *this;
       }
 
-      template<typename... _UElements, typename = typename
+      template<typename... _UElements>
+	typename
 	       enable_if<sizeof...(_UElements)
-			 == sizeof...(_Elements)>::type>
-        tuple&
+			 == sizeof...(_Elements), tuple&>::type
         operator=(const tuple<_UElements...>& __in)
         {
 	  static_cast<_Inherited&>(*this) = __in;
 	  return *this;
 	}
 
-      template<typename... _UElements, typename = typename
+      template<typename... _UElements>
+	typename
 	       enable_if<sizeof...(_UElements)
-			 == sizeof...(_Elements)>::type>
-        tuple&
+			 == sizeof...(_Elements), tuple&>::type
         operator=(tuple<_UElements...>&& __in)
         {
 	  static_cast<_Inherited&>(*this) = std::move(__in);
diff --git a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
index 8b30666..4de400d 100644
--- a/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
+++ b/libstdc++-v3/testsuite/20_util/any/misc/any_cast_neg.cc
@@ -26,5 +26,5 @@ void test01()
   using std::any_cast;
 
   const any y(1);
-  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 432 }
+  any_cast<int&>(y); // { dg-error "qualifiers" "" { target { *-*-* } } 453 }
 }


More information about the Libstdc++ mailing list