diff options
author | Jonathan Wakely <jwakely@redhat.com> | 2017-01-20 02:36:16 +0000 |
---|---|---|
committer | Jonathan Wakely <redi@gcc.gnu.org> | 2017-01-20 02:36:16 +0000 |
commit | a3a1620bb840d62dbde06ce0290e8e5cfcbbf18b (patch) | |
tree | a8129bd7cd698ffbc306fef0a1ba2f58053e5eab | |
parent | 198766b6488cf0b50b3cff97099fb1c0482a9f3a (diff) | |
download | gcc-a3a1620bb840d62dbde06ce0290e8e5cfcbbf18b.zip gcc-a3a1620bb840d62dbde06ce0290e8e5cfcbbf18b.tar.gz gcc-a3a1620bb840d62dbde06ce0290e8e5cfcbbf18b.tar.bz2 |
PR72792 PR72793 relax requirements on rebind members
PR libstdc++/72792
PR libstdc++/72793
* include/bits/alloc_traits.h (__allocator_traits_base::__rebind):
Replace with class template using void_t.
(__alloc_rebind): Define in terms of
__allocator_traits_base::__rebind.
(allocator_traits): Remove unconditional static_assert for
rebind_alloc.
* include/bits/ptr_traits.h (__replace_first_arg): Remove type member.
(pointer_traits::__rebind): Replace with class template using void_t.
(pointer_traits::rebind): Define in terms of __rebind.
(pointer_traits): Remove unconditional static_assert for rebind.
* testsuite/20_util/allocator_traits/members/rebind_alloc.cc: New test.
* testsuite/20_util/pointer_traits/rebind.cc: New test.
From-SVN: r244680
-rw-r--r-- | libstdc++-v3/ChangeLog | 15 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/alloc_traits.h | 17 | ||||
-rw-r--r-- | libstdc++-v3/include/bits/ptr_traits.h | 13 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/allocator_traits/members/rebind_alloc.cc | 81 | ||||
-rw-r--r-- | libstdc++-v3/testsuite/20_util/pointer_traits/rebind.cc | 68 |
5 files changed, 180 insertions, 14 deletions
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index b4be6e5..c8cdaaa 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,20 @@ 2017-01-20 Jonathan Wakely <jwakely@redhat.com> + PR libstdc++/72792 + PR libstdc++/72793 + * include/bits/alloc_traits.h (__allocator_traits_base::__rebind): + Replace with class template using void_t. + (__alloc_rebind): Define in terms of + __allocator_traits_base::__rebind. + (allocator_traits): Remove unconditional static_assert for + rebind_alloc. + * include/bits/ptr_traits.h (__replace_first_arg): Remove type member. + (pointer_traits::__rebind): Replace with class template using void_t. + (pointer_traits::rebind): Define in terms of __rebind. + (pointer_traits): Remove unconditional static_assert for rebind. + * testsuite/20_util/allocator_traits/members/rebind_alloc.cc: New test. + * testsuite/20_util/pointer_traits/rebind.cc: New test. + PR libstdc++/69321 * include/experimental/any (__any_caster): Avoid instantiating manager function for types that can't be stored in any. diff --git a/libstdc++-v3/include/bits/alloc_traits.h b/libstdc++-v3/include/bits/alloc_traits.h index fc8f053b5..a836711 100644 --- a/libstdc++-v3/include/bits/alloc_traits.h +++ b/libstdc++-v3/include/bits/alloc_traits.h @@ -44,8 +44,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION struct __allocator_traits_base { - template<typename _Alloc, typename _Up> - using __rebind = typename _Alloc::template rebind<_Up>::other; + template<typename _Tp, typename _Up, typename = void> + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template<typename _Tp, typename _Up> + struct __rebind<_Tp, _Up, + __void_t<typename _Tp::template rebind<_Up>::other>> + { using type = typename _Tp::template rebind<_Up>::other; }; protected: template<typename _Tp> @@ -71,9 +76,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION }; template<typename _Alloc, typename _Up> - using __alloc_rebind = __detected_or_t_<__replace_first_arg_t, - __allocator_traits_base::__rebind, - _Alloc, _Up>; + using __alloc_rebind + = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; /** * @brief Uniform interface to all allocator types. @@ -184,9 +188,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using rebind_traits = allocator_traits<rebind_alloc<_Tp>>; - static_assert(!is_same<rebind_alloc<value_type>, __undefined>::value, - "allocator defines rebind or is like Alloc<T, Args>"); - private: template<typename _Alloc2> static auto diff --git a/libstdc++-v3/include/bits/ptr_traits.h b/libstdc++-v3/include/bits/ptr_traits.h index 9fab9df..d390d04 100644 --- a/libstdc++-v3/include/bits/ptr_traits.h +++ b/libstdc++-v3/include/bits/ptr_traits.h @@ -56,7 +56,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Given Template<T, ...> and U return Template<U, ...>, otherwise invalid. template<typename _Tp, typename _Up> struct __replace_first_arg - { using type = __undefined; }; + { }; template<template<typename, typename...> class _Template, typename _Up, typename _Tp, typename... _Types> @@ -84,8 +84,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template<typename _Tp> using __difference_type = typename _Tp::difference_type; + template<typename _Tp, typename _Up, typename = void> + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + template<typename _Tp, typename _Up> - using __rebind = typename _Tp::template rebind<_Up>; + struct __rebind<_Tp, _Up, __void_t<typename _Tp::template rebind<_Up>>> + { using type = typename _Tp::template rebind<_Up>; }; public: /// The pointer type. @@ -101,8 +105,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// A pointer to a different type. template<typename _Up> - using rebind - = __detected_or_t_<__replace_first_arg_t, __rebind, _Ptr, _Up>; + using rebind = typename __rebind<_Ptr, _Up>::type; static _Ptr pointer_to(__make_not_void<element_type>& __e) @@ -110,8 +113,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION static_assert(!is_same<element_type, __undefined>::value, "pointer type defines element_type or is like SomePointer<T, Args>"); - static_assert(!is_same<rebind<element_type>, __undefined>::value, - "pointer type defines rebind<U> or is like SomePointer<T, Args>"); }; /** diff --git a/libstdc++-v3/testsuite/20_util/allocator_traits/members/rebind_alloc.cc b/libstdc++-v3/testsuite/20_util/allocator_traits/members/rebind_alloc.cc new file mode 100644 index 0000000..60a6249 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/allocator_traits/members/rebind_alloc.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2017 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++11 } } + +#include <memory> + +using std::is_same; + +template<typename T, typename U> + using Rebind = typename std::allocator_traits<T>::template rebind_alloc<U>; + +template<typename T> + struct HasRebind { + using value_type = T; + template<typename U> struct rebind { using other = std::allocator<U>; }; + }; + +static_assert(is_same<Rebind<HasRebind<int>, long>, + std::allocator<long>>::value, + "nested alias template is used"); + +template<typename T> + struct NoRebind0 { + using value_type = T; + }; + +static_assert(is_same<Rebind<NoRebind0<int>, long>, + NoRebind0<long>>::value, + "first template argument is replaced"); + +template<typename T, typename> + struct NoRebind1 { + using value_type = T; + }; + +static_assert(is_same<Rebind<NoRebind1<int, void>, long>, + NoRebind1<long, void>>::value, + "first template argument is replaced"); + +template<typename T, typename, typename> + struct NoRebind2 { + using value_type = T; + }; + +static_assert(is_same<Rebind<NoRebind2<int, void, void>, long>, + NoRebind2<long, void, void>>::value, + "first template argument is replaced"); + +template<typename T, typename...> + struct NoRebindN { + using value_type = T; + }; + +static_assert(is_same<Rebind<NoRebindN<int>, long>, + NoRebindN<long>>::value, + "first template argument is replaced"); +static_assert(is_same<Rebind<NoRebindN<int, void>, long>, + NoRebindN<long, void>>::value, + "first template argument is replaced"); + +template<typename T, int = 0> + struct CannotRebind { + using value_type = T; + }; +// PR libstdc++/72792 specialization of allocator_traits is still well-formed: +std::allocator_traits<CannotRebind<int>>::value_type v; diff --git a/libstdc++-v3/testsuite/20_util/pointer_traits/rebind.cc b/libstdc++-v3/testsuite/20_util/pointer_traits/rebind.cc new file mode 100644 index 0000000..a628159 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/pointer_traits/rebind.cc @@ -0,0 +1,68 @@ +// Copyright (C) 2017 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++11 } } + +#include <memory> + +using std::is_same; + +template<typename T, typename U> + using Rebind = typename std::pointer_traits<T>::template rebind<U>; + +template<typename T> + struct HasRebind { + template<typename U> using rebind = U*; + }; + +static_assert(is_same<Rebind<HasRebind<int>, long>, + long*>::value, + "nested alias template is used"); + +template<typename T> struct NoRebind0 { }; + +static_assert(is_same<Rebind<NoRebind0<int>, long>, + NoRebind0<long>>::value, + "first template argument is replaced"); + +template<typename T, typename> struct NoRebind1 { }; + +static_assert(is_same<Rebind<NoRebind1<int, void>, long>, + NoRebind1<long, void>>::value, + "first template argument is replaced"); + +template<typename T, typename, typename> struct NoRebind2 { }; + +static_assert(is_same<Rebind<NoRebind2<int, void, void>, long>, + NoRebind2<long, void, void>>::value, + "first template argument is replaced"); + +template<typename T, typename...> struct NoRebindN { }; + +static_assert(is_same<Rebind<NoRebindN<int>, long>, + NoRebindN<long>>::value, + "first template argument is replaced"); +static_assert(is_same<Rebind<NoRebindN<int, void>, long>, + NoRebindN<long, void>>::value, + "first template argument is replaced"); + +template<typename T, int = 0> + struct CannotRebind { + using element_type = T; + }; +// PR libstdc++/72793 specialization of pointer_traits is still well-formed: +std::pointer_traits<CannotRebind<int>>::element_type e; |