nonesuch is insufficiently useless (lwg2996)
authorNina Dinka Ranns <dinka.ranns@gmail.com>
Tue, 14 May 2019 15:48:27 +0000 (15:48 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Tue, 14 May 2019 15:48:27 +0000 (16:48 +0100)
2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>

nonesuch is insufficiently useless (lwg2996)
* include/std/type_traits (struct __nonesuch): Added private base
class to make __nonesuch not an aggregate and removed deleted default
constructor.
* include/bits/stl_pair.h (struct __nonesuch_no_braces): Removed.
(operator=(const pair&)): Use __nonesuch instead of
__nonesuch_no_braces.
(operator=(pair&&)): Likewise
* include/std/tuple (operator=(const tuple&)): Use __nonesuch instead
of __nonesuch_no_braces.
(operator=(tuple&&)): Likewise
* include/experimental/type_traits (struct nonesuch): Added private
base class to make nonesuch not an aggregate and removed deleted
default constructor.
* testsuite/20_util/nonesuch/nonesuch.cc: New.
* testsuite/experimental/type_traits/nonesuch.cc: New.

From-SVN: r271175

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/stl_pair.h
libstdc++-v3/include/experimental/type_traits
libstdc++-v3/include/std/tuple
libstdc++-v3/include/std/type_traits
libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc [new file with mode: 0644]
libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc [new file with mode: 0644]

index c2466cefaa595bfe81cbbe9ee9073afa928f84b0..5a21ebcb0228155244b9539b5c43c2fccd71a782 100644 (file)
@@ -1,3 +1,22 @@
+2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+
+       nonesuch is insufficiently useless (lwg2996)
+       * include/std/type_traits (struct __nonesuch): Added private base
+       class to make __nonesuch not an aggregate and removed deleted default
+       constructor.
+       * include/bits/stl_pair.h (struct __nonesuch_no_braces): Removed.
+       (operator=(const pair&)): Use __nonesuch instead of
+       __nonesuch_no_braces.
+       (operator=(pair&&)): Likewise
+       * include/std/tuple (operator=(const tuple&)): Use __nonesuch instead
+       of __nonesuch_no_braces.
+       (operator=(tuple&&)): Likewise
+       * include/experimental/type_traits (struct nonesuch): Added private
+       base class to make nonesuch not an aggregate and removed deleted
+       default constructor.
+       * testsuite/20_util/nonesuch/nonesuch.cc: New.
+       * testsuite/experimental/type_traits/nonesuch.cc: New.
+
 2019-05-14  Jonathan Wakely  <jwakely@redhat.com>
 
        * include/bits/std_function.h (_Simple_type_wrapper): Remove.
index f99b774c21e7f52d12ca7e93be082eae96ed3411..c04f169bb6c70d8af05ca828c54beb5b09f249e1 100644 (file)
@@ -180,13 +180,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        return false;
       }
   };
-
-  // PR libstdc++/79141, a utility type for preventing
-  // initialization of an argument of a disabled assignment
-  // operator from a pair of empty braces.
-  struct __nonesuch_no_braces : std::__nonesuch {
-    explicit __nonesuch_no_braces(const __nonesuch&) = delete;
-  };
 #endif // C++11
 
   template<typename _U1, typename _U2> class __pair_base
@@ -393,7 +386,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator=(typename conditional<
                __and_<is_copy_assignable<_T1>,
                       is_copy_assignable<_T2>>::value,
-               const pair&, const __nonesuch_no_braces&>::type __p)
+               const pair&, const __nonesuch&>::type __p)
       {
        first = __p.first;
        second = __p.second;
@@ -404,7 +397,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       operator=(typename conditional<
                __and_<is_move_assignable<_T1>,
                       is_move_assignable<_T2>>::value,
-               pair&&, __nonesuch_no_braces&&>::type __p)
+               pair&&, __nonesuch&&>::type __p)
       noexcept(__and_<is_nothrow_move_assignable<_T1>,
                      is_nothrow_move_assignable<_T2>>::value)
       {
index 09743c5e92be35fd07e817fd82468d67dc96f1d5..c2b2dcc2739bd58976c55dbf64ba8dbe7dfb9467 100644 (file)
@@ -227,9 +227,9 @@ inline namespace fundamentals_v2
 
 template<typename...> using void_t = void;
 
-struct nonesuch
+struct __nonesuchbase {};
+struct nonesuch : private __nonesuchbase
 {
-  nonesuch() = delete;
   ~nonesuch() = delete;
   nonesuch(nonesuch const&) = delete;
   void operator=(nonesuch const&) = delete;
index 956e031ae9d264b26c97f5564fb92de3f4969e8b..a28111749f0b39a0390012ced0257e25d05b11b4 100644 (file)
@@ -832,7 +832,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       tuple&
       operator=(typename conditional<__assignable<const _Elements&...>(),
                                     const tuple&,
-                                    const __nonesuch_no_braces&>::type __in)
+                                    const __nonesuch&>::type __in)
       noexcept(__nothrow_assignable<const _Elements&...>())
       {
        this->_M_assign(__in);
@@ -842,7 +842,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       tuple&
       operator=(typename conditional<__assignable<_Elements...>(),
                                     tuple&&,
-                                    __nonesuch_no_braces&&>::type __in)
+                                    __nonesuch&&>::type __in)
       noexcept(__nothrow_assignable<_Elements...>())
       {
        this->_M_assign(std::move(__in));
@@ -1243,7 +1243,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       tuple&
       operator=(typename conditional<__assignable<const _T1&, const _T2&>(),
                                     const tuple&,
-                                    const __nonesuch_no_braces&>::type __in)
+                                    const __nonesuch&>::type __in)
       noexcept(__nothrow_assignable<const _T1&, const _T2&>())
       {
        this->_M_assign(__in);
@@ -1253,7 +1253,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       tuple&
       operator=(typename conditional<__assignable<_T1, _T2>(),
                                     tuple&&,
-                                    __nonesuch_no_braces&&>::type __in)
+                                    __nonesuch&&>::type __in)
       noexcept(__nothrow_assignable<_T1, _T2>())
       {
        this->_M_assign(std::move(__in));
index f68d366269dde56093f4d40d0cc2bf9e5535e5ae..b1c3e943e791cc914b5c598b0590102c0e67424e 100644 (file)
@@ -2792,8 +2792,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
              __call_is_nothrow_<_Fn, _Args...>>::type
     { };
 
-  struct __nonesuch {
-    __nonesuch() = delete;
+  struct __nonesuchbase {};
+  struct __nonesuch : private __nonesuchbase {
     ~__nonesuch() = delete;
     __nonesuch(__nonesuch const&) = delete;
     void operator=(__nonesuch const&) = delete;
diff --git a/libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc b/libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc
new file mode 100644 (file)
index 0000000..100d7e3
--- /dev/null
@@ -0,0 +1,39 @@
+// 2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++14 } }
+
+#include <type_traits>
+// Example taken from LWG2960
+
+using std::__nonesuch;
+struct such {};
+void f(const such&){};
+void f(const std::__nonesuch&);
+
+int main(){
+ static_assert(!std::is_default_constructible<__nonesuch>::value,
+                "__nonesuch is default constructible");
+ static_assert(!std::is_copy_constructible<__nonesuch>::value,
+                "__nonesuch is copy constructible");
+ static_assert(!std::is_assignable<__nonesuch, __nonesuch>::value,
+                "__nonesuch is assignable");
+ static_assert(!std::is_destructible<__nonesuch>::value,
+                "__nonesuch is destructible");
+ f({});
+}
diff --git a/libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc b/libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc
new file mode 100644 (file)
index 0000000..2e62402
--- /dev/null
@@ -0,0 +1,40 @@
+// 2019-05-14  Nina Dinka Ranns  <dinka.ranns@gmail.com>
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++14 } }
+
+#include <experimental/type_traits>
+// Example taken from LWG2960
+
+using std::experimental::nonesuch;
+
+struct such {};
+void f(const such&){};
+void f(const nonesuch&);
+
+int main(){
+ static_assert(!std::is_default_constructible<nonesuch>::value,
+                "nonesuch is default constructible");
+ static_assert(!std::is_copy_constructible<nonesuch>::value,
+                "nonesuch is copy constructible");
+ static_assert(!std::is_assignable<nonesuch,nonesuch>::value,
+                "nonesuch is assignable");
+ static_assert(!std::is_destructible<nonesuch>::value,
+                "nonesuch is destructible");
+ f({});
+}