]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
optional (_Has_addressof): Check for non-member operator&.
authorJonathan Wakely <jwakely@redhat.com>
Wed, 12 Nov 2014 00:16:19 +0000 (00:16 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 12 Nov 2014 00:16:19 +0000 (00:16 +0000)
* include/experimental/optional (_Has_addressof): Check for non-member
operator&.
* testsuite/experimental/optional/observers/2.cc: Add operator&.
* testsuite/experimental/optional/constexpr/observers/2.cc: Likewise.

From-SVN: r217397

libstdc++-v3/ChangeLog
libstdc++-v3/include/experimental/optional
libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc
libstdc++-v3/testsuite/experimental/optional/observers/2.cc

index 4a17fd0b9b3fe4ca9171e666f80434a9765eb758..0c9d430c70cc5eda07353e265a8b987c9b1cad52 100644 (file)
@@ -1,3 +1,10 @@
+2014-11-12  Jonathan Wakely  <jwakely@redhat.com>
+
+       * include/experimental/optional (_Has_addressof): Check for non-member
+       operator&.
+       * testsuite/experimental/optional/observers/2.cc: Add operator&.
+       * testsuite/experimental/optional/constexpr/observers/2.cc: Likewise.
+
 2014-11-11  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/std/type_traits (__void_t): Define new alias template.
index 7e01abedb76d4ebce3b3812536da7e7ff59b8476..2d3127a7b1d460caf7ff2db8073ad40eaeaa654b 100644 (file)
@@ -127,13 +127,23 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   __throw_bad_optional_access(const char* __s)
   { _GLIBCXX_THROW_OR_ABORT(bad_optional_access(__s)); }
 
-  template<typename _Tp, typename _Sfinae = void>
-    struct _Has_addressof_impl : std::false_type { };
+  template<typename _Tp, typename = void>
+    struct _Has_addressof_mem : std::false_type { };
 
   template<typename _Tp>
-    struct _Has_addressof_impl<_Tp,
-      decltype( std::declval<const _Tp&>().operator&(), void() )>
-      : std::true_type { };
+    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&.
@@ -143,7 +153,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     * declval<_Tp * const&>().operator&()).
     */
   template<typename _Tp>
-    struct _Has_addressof : _Has_addressof_impl<_Tp>::type { };
+    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
index 14b5e3b1f523d3108b78c0b7d201f197b92ee3b1..2c9215c69243e9a47e713135616f74cbb42497a2 100644 (file)
@@ -26,6 +26,8 @@
 struct value_type
 {
   int i;
+
+  void* operator&() { return nullptr; } // N.B. non-const
 };
 
 int main()
index 8499b4779d22d9d085346c179595a0edfce219c7..9fb2edbd89a5137550e13b8dd55327fd2d8215ce 100644 (file)
@@ -26,6 +26,8 @@ struct value_type
   int i;
 };
 
+void* operator&(const value_type&) = delete;
+
 int main()
 {
   std::experimental::optional<value_type> o { value_type { 51 } };