Tested on Linux x86_64 nonesuch is insufficiently useless (lwg2996)
2019-05-14 Nina Dinka Ranns <dinka.ra...@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
Index: libstdc++-v3/include/bits/stl_pair.h =================================================================== --- libstdc++-v3/include/bits/stl_pair.h (revision 270630) +++ libstdc++-v3/include/bits/stl_pair.h (working copy) @@ -178,13 +178,6 @@ 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 @@ -378,7 +371,7 @@ 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; @@ -389,7 +382,7 @@ 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: libstdc++-v3/include/experimental/type_traits =================================================================== --- libstdc++-v3/include/experimental/type_traits (revision 270630) +++ libstdc++-v3/include/experimental/type_traits (working copy) @@ -226,9 +226,9 @@ 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: libstdc++-v3/include/std/tuple =================================================================== --- libstdc++-v3/include/std/tuple (revision 270630) +++ libstdc++-v3/include/std/tuple (working copy) @@ -816,7 +816,7 @@ 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); @@ -826,7 +826,7 @@ 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)); @@ -1204,7 +1204,7 @@ 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); @@ -1214,7 +1214,7 @@ 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: libstdc++-v3/include/std/type_traits =================================================================== --- libstdc++-v3/include/std/type_traits (revision 270630) +++ libstdc++-v3/include/std/type_traits (working copy) @@ -2769,8 +2769,8 @@ __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; Index: libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc =================================================================== --- libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc (nonexistent) +++ libstdc++-v3/testsuite/20_util/nonesuch/nonesuch.cc (working copy) @@ -0,0 +1,39 @@ +// 2019-05-14 Nina Dinka Ranns <dinka.ra...@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({}); +} Index: libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc =================================================================== --- libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc (nonexistent) +++ libstdc++-v3/testsuite/experimental/type_traits/nonesuch.cc (working copy) @@ -0,0 +1,40 @@ +// 2019-05-14 Nina Dinka Ranns <dinka.ra...@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({}); +}