Makefile.am: Add new header.
authorJonathan Wakely <jwakely.gcc@gmail.com>
Sat, 9 Jul 2011 13:45:56 +0000 (13:45 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Sat, 9 Jul 2011 13:45:56 +0000 (14:45 +0100)
2011-07-09  Jonathan Wakely  <jwakely.gcc@gmail.com>

* include/Makefile.am: Add new header.
* include/Makefile.in: Regenerate.
* include/std/scoped_allocator: New.
* doc/xml/manual/status_cxx200x.xml: Update.
* testsuite/20_util/scoped_allocator/1.cc: New.
* testsuite/20_util/scoped_allocator/propagation.cc: New.
* testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
* testsuite/20_util/scoped_allocator/requirements/
explicit_instantiation.cc: New.

From-SVN: r176079

libstdc++-v3/ChangeLog
libstdc++-v3/doc/xml/manual/status_cxx200x.xml
libstdc++-v3/include/Makefile.am
libstdc++-v3/include/Makefile.in
libstdc++-v3/include/std/scoped_allocator [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/scoped_allocator/1.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/typedefs.cc [new file with mode: 0644]

index 1304b9241e2800599a953fef85abfd8502d027d4..6424c558aced8fc774ddbea6dee95c4b119e7ee5 100644 (file)
@@ -1,3 +1,15 @@
+2011-07-09  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       * include/Makefile.am: Add new header.
+       * include/Makefile.in: Regenerate.
+       * include/std/scoped_allocator: New.
+       * doc/xml/manual/status_cxx200x.xml: Update.
+       * testsuite/20_util/scoped_allocator/1.cc: New.
+       * testsuite/20_util/scoped_allocator/propagation.cc: New.
+       * testsuite/20_util/scoped_allocator/requirements/typedefs.cc: New.
+       * testsuite/20_util/scoped_allocator/requirements/
+       explicit_instantiation.cc: New.
+
 2011-07-09  Jonathan Wakely  <jwakely.gcc@gmail.com>
 
        * include/bits/stl_vector.h: Use new allocator model in C++0x mode.
index 5c4bc5de0bd98c49588f2ada93953b85f0678468..88e238f23556280c9b19c9c00fe06d2bad638cc4 100644 (file)
@@ -1009,52 +1009,47 @@ particular release.
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
+      <?dbhtml bgcolor="#B0B0B0" ?>
       <entry>20.12</entry>
       <entry>Scoped allocator adaptor</entry>
-      <entry/>
+      <entry>Partial</entry>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry>20.12.1</entry>
       <entry>Header <code>&lt;scoped_allocator&gt;</code> synopsis</entry>
       <entry/>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry>20.12.2</entry>
       <entry>Scoped allocator adaptor member types</entry>
-      <entry>N</entry>
+      <entry>Y</entry>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry>20.12.3</entry>
       <entry>Scoped allocator adaptor constructors</entry>
-      <entry>N</entry>
+      <entry>Y</entry>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
+      <?dbhtml bgcolor="#B0B0B0" ?>
       <entry>20.12.4</entry>
       <entry>Scoped allocator adaptor members</entry>
-      <entry>N</entry>
+      <entry>Partial</entry>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry>20.12.5</entry>
       <entry>Scoped allocator operators</entry>
-      <entry>N</entry>
+      <entry>Y</entry>
       <entry/>
     </row>
     <row>
-      <?dbhtml bgcolor="#C8B0B0" ?>
       <entry>20.13</entry>
       <entry>Class <code>type_index</code></entry>
-      <entry>N</entry>
+      <entry>Y</entry>
       <entry/>
     </row>
     <row>
index b6a0116872f47fc23c7b6c1273894beedcec766d..c926a3133aaae7bb0c461a9342669adb13752ee2 100644 (file)
@@ -58,6 +58,7 @@ std_headers = \
        ${std_srcdir}/random \
        ${std_srcdir}/ratio \
        ${std_srcdir}/regex \
+       ${std_srcdir}/scoped_allocator \
        ${std_srcdir}/set \
        ${std_srcdir}/sstream \
        ${std_srcdir}/stack \
index 750e67f89f4e62849ebede3437024b32a229ce0b..c26eab0c6a0207fafa39f411df0ddf283dd53700 100644 (file)
@@ -310,6 +310,7 @@ std_headers = \
        ${std_srcdir}/random \
        ${std_srcdir}/ratio \
        ${std_srcdir}/regex \
+       ${std_srcdir}/scoped_allocator \
        ${std_srcdir}/set \
        ${std_srcdir}/sstream \
        ${std_srcdir}/stack \
diff --git a/libstdc++-v3/include/std/scoped_allocator b/libstdc++-v3/include/std/scoped_allocator
new file mode 100644 (file)
index 0000000..bde996c
--- /dev/null
@@ -0,0 +1,373 @@
+// <scoped_allocator> -*- C++ -*-
+
+// Copyright (C) 2011 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.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file include/scoped_allocator
+ *  This is a Standard C++ Library header.
+ */
+
+#ifndef _SCOPED_ALLOCATOR
+#define _SCOPED_ALLOCATOR 1
+
+#pragma GCC system_header
+
+#ifndef __GXX_EXPERIMENTAL_CXX0X__
+# include <bits/c++0x_warning.h>
+#else
+
+#include <utility>
+#include <tuple>
+#include <bits/alloc_traits.h>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
+
+  template<template<typename> class _Pred, typename... _Allocs>
+    struct __any_of;
+
+  template<template<typename> class _Pred, typename _Alloc, typename... _Allocs>
+    struct __any_of<_Pred, _Alloc, _Allocs...>
+    : __or_<_Pred<_Alloc>, __any_of<_Pred, _Allocs...>>
+    { };
+
+  template<template<typename> class _Pred, typename _Alloc>
+    struct __any_of<_Pred, _Alloc>
+    : _Pred<_Alloc>
+    { };
+
+  /**
+   * @addtogroup allocators
+   * @{
+   */
+
+  template<typename _Alloc>
+    struct __propagate_on_copy
+    : allocator_traits<_Alloc>::propagate_on_container_copy_assignment
+    { };
+  template<typename _Alloc>
+    struct __propagate_on_move
+    : allocator_traits<_Alloc>::propagate_on_container_move_assignment
+    { };
+  template<typename _Alloc>
+    struct __propagate_on_swap
+    : allocator_traits<_Alloc>::propagate_on_container_swap
+    { };
+
+  
+  template<typename _Alloc>
+    inline auto
+    __do_outermost(_Alloc& __a, _Alloc&) -> decltype(__a.outer_allocator())
+    { return __a.outer_allocator(); }
+
+  template<typename _Alloc>
+    inline _Alloc&
+    __do_outermost(_Alloc& __a, ...)
+    { return __a; }
+
+  template<typename _Alloc>
+    inline auto
+    __outermost(_Alloc& __a) -> decltype(__do_outermost(__a, __a))
+    { return __do_outermost(__a, __a); }
+
+  template<typename _OuterAlloc, typename... _InnerAllocs>
+    class scoped_allocator_adaptor;
+
+      template<typename...> struct __inner_type_impl;
+
+      template<typename _Outer>
+      struct __inner_type_impl<_Outer>
+      {
+       typedef scoped_allocator_adaptor<_Outer> __type;
+
+        __inner_type_impl() = default;
+        __inner_type_impl(const __inner_type_impl&) = default;
+        __inner_type_impl(__inner_type_impl&&) = default;
+
+       template<typename _Alloc>
+         __inner_type_impl(const __inner_type_impl<_Alloc>& __other)
+         { }
+
+       template<typename _Alloc>
+         __inner_type_impl(__inner_type_impl<_Alloc>&& __other)
+         { }
+
+       __type& _M_get(__type* __p) noexcept { return *__p; }
+       const __type& _M_get(const __type* __p) const noexcept { return *__p; }
+
+       tuple<> _M_tie() const noexcept { return tuple<>(); }
+
+       bool operator==(const __inner_type_impl&) const noexcept
+        { return true; }
+      };
+
+      template<typename _Outer, typename _InnerHead, typename... _InnerTail>
+      struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...>
+      {
+       typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type;
+
+       __inner_type_impl() = default;
+        __inner_type_impl(const __inner_type_impl&) = default;
+        __inner_type_impl(__inner_type_impl&&) = default;
+
+       template<typename... _Allocs>
+         __inner_type_impl(const __inner_type_impl<_Allocs...>& __other)
+         : _M_inner(__other._M_inner) { }
+
+       template<typename... _Allocs>
+         __inner_type_impl(__inner_type_impl<_Allocs...>&& __other)
+         : _M_inner(std::move(__other._M_inner)) { }
+
+       template<typename... _Args>
+         explicit
+         __inner_type_impl(_Args&&... __args)
+         : _M_inner(std::forward<_Args>(__args)...) { }
+
+       __type& _M_get(void*) noexcept { return _M_inner; }
+       const __type& _M_get(const void*) const noexcept { return _M_inner; }
+
+       tuple<const _InnerHead&, const _InnerTail&...> _M_tie() const noexcept
+       { return _M_inner._M_tie(); }
+
+       bool operator==(const __inner_type_impl& __other) const noexcept
+       { return _M_inner == __other._M_inner; }
+
+      private:
+       template<typename...> friend class __inner_type_impl;
+       template<typename, typename...> friend class scoped_allocator_adaptor;
+
+       __type _M_inner;
+      };
+
+  template<typename _OuterAlloc, typename... _InnerAllocs>
+    class scoped_allocator_adaptor
+    : public _OuterAlloc
+    {
+      typedef allocator_traits<_OuterAlloc> __traits;
+
+      typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type;
+      __inner_type _M_inner;
+
+      template<typename _Outer, typename... _Inner>
+        friend class scoped_allocator_adaptor;
+
+      template<typename...>
+        friend class __inner_type_impl;
+
+      tuple<const _OuterAlloc&, const _InnerAllocs&...>
+      _M_tie() const noexcept
+      { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); }
+
+      
+      template<typename _Tp, typename... _Args>
+        void _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args)
+        {
+          auto& __outer = __outermost(*this);
+         typedef typename std::decay<decltype(__outer)>::type __outer_type;
+          typedef allocator_traits<__outer_type> __o_traits;
+          __o_traits::construct(__outer, __p, std::forward<_Args>(__args)...);
+        }
+
+      typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_;
+      typedef __uses_alloc2<typename __inner_type::__type> __uses_alloc2_;
+
+      template<typename _Tp, typename... _Args>
+        void _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args)
+        {
+          auto& __outer = __outermost(*this);
+         typedef typename std::decay<decltype(__outer)>::type __outer_type;
+          typedef allocator_traits<__outer_type> __o_traits;
+          __o_traits::construct(__outer, __p, allocator_arg, inner_allocator(),
+                                std::forward<_Args>(__args)...);
+        }
+
+      template<typename _Tp, typename... _Args>
+        void _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args)
+        {
+         auto& __outer = __outermost(*this);
+         typedef typename std::decay<decltype(__outer)>::type __outer_type;
+          typedef allocator_traits<__outer_type> __o_traits;
+          __o_traits::construct(__outer, __p, std::forward<_Args>(__args)...,
+                                inner_allocator());
+        }
+
+      template<typename _Alloc>
+        static _Alloc
+        _S_select_on_copy(const _Alloc& __a)
+        {
+          typedef allocator_traits<_Alloc> __a_traits;
+          return __a_traits::select_on_container_copy_construction(__a);
+        }
+
+      template<int... _Indices>
+        scoped_allocator_adaptor(tuple<const _OuterAlloc&,
+                                       const _InnerAllocs&...> __refs,
+                                 _Index_tuple<_Indices...>)
+        : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))),
+          _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...)
+        { }
+
+    public:
+      typedef _OuterAlloc                       outer_allocator_type;
+      typedef typename __inner_type::__type     inner_allocator_type;
+
+      typedef typename __traits::value_type             value_type;
+      typedef typename __traits::size_type              size_type;
+      typedef typename __traits::difference_type        difference_type;
+      typedef typename __traits::pointer                pointer;
+      typedef typename __traits::const_pointer          const_pointer;
+      typedef typename __traits::void_pointer           void_pointer;
+      typedef typename __traits::const_void_pointer     const_void_pointer;
+
+      typedef typename conditional<
+        __any_of<__propagate_on_copy, _OuterAlloc, _InnerAllocs...>::value,
+        true_type, false_type>::type propagate_on_container_copy_assignment;
+      typedef typename conditional<
+        __any_of<__propagate_on_move, _OuterAlloc, _InnerAllocs...>::value,
+        true_type, false_type>::type propagate_on_container_move_assignment;
+      typedef typename conditional<
+        __any_of<__propagate_on_swap, _OuterAlloc, _InnerAllocs...>::value,
+        true_type, false_type>::type propagate_on_container_swap;
+
+      template <class _Tp>
+        struct rebind
+        {
+          // TODO: use rebind_alloc<Tp> instead of __rebind_alloc<Tp>::__type
+          typedef scoped_allocator_adaptor<
+            typename __traits::template __rebind_alloc<_Tp>::__type,
+            _InnerAllocs...> other;
+        };
+
+      scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { }
+
+      template<typename _Outer2>
+        scoped_allocator_adaptor(_Outer2&& __outer,
+                                 const _InnerAllocs&... __inner)
+        : _OuterAlloc(std::forward<_Outer2>(__outer)),
+          _M_inner(__inner...)
+        { }
+
+      scoped_allocator_adaptor(const scoped_allocator_adaptor& __other)
+      : _OuterAlloc(__other.outer_allocator()),
+       _M_inner(__other._M_inner)
+      { }
+
+      scoped_allocator_adaptor(scoped_allocator_adaptor&& __other)
+      : _OuterAlloc(std::move(__other.outer_allocator())),
+       _M_inner(std::move(__other._M_inner))
+      { }
+
+      template<typename _Outer2>
+        scoped_allocator_adaptor(
+            const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other)
+        : _OuterAlloc(__other.outer_allocator()),
+          _M_inner(__other._M_inner)
+        { }
+
+      template<typename _Outer2>
+        scoped_allocator_adaptor(
+            scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other)
+        : _OuterAlloc(std::move(__other.outer_allocator())),
+          _M_inner(std::move(__other._M_inner))
+        { }
+
+      inner_allocator_type& inner_allocator() noexcept
+      { return _M_inner._M_get(this); }
+
+      const inner_allocator_type& inner_allocator() const noexcept
+      { return _M_inner._M_get(this); }
+
+      outer_allocator_type& outer_allocator() noexcept
+      { return static_cast<_OuterAlloc&>(*this); }
+
+      const outer_allocator_type& outer_allocator() const noexcept
+      { return static_cast<const _OuterAlloc&>(*this); }
+
+      pointer allocate(size_type __n)
+      { return __traits::allocate(outer_allocator(), __n); }
+
+      pointer allocate(size_type __n, const_void_pointer __hint)
+      { return __traits::allocate(outer_allocator(), __n, __hint); }
+
+      void deallocate(pointer __p, size_type __n)
+      { return __traits::deallocate(outer_allocator(), __p, __n); }
+
+      size_type max_size() const
+      { return __traits::max_size(outer_allocator()); }
+
+      template<typename _Tp, typename... _Args>
+        void construct(_Tp* __p, _Args&&... __args)
+        {
+          auto& __inner = inner_allocator();
+          auto __use_tag
+            = __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
+          _M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
+        }
+
+      // TODO: construct pairs
+
+      template<typename _Tp>
+        void destroy(_Tp* __p)
+        {
+          auto& __outer = __outermost(*this);
+         typedef typename std::decay<decltype(__outer)>::type __outer_type;
+          allocator_traits<__outer_type>::destroy(__outer, __p);
+        }
+
+      scoped_allocator_adaptor
+      select_on_container_copy_construction() const
+      {
+        typedef typename _Build_index_tuple<sizeof...(_InnerAllocs)>::__type
+           _Indices;
+        return scoped_allocator_adaptor(_M_tie(), _Indices());
+      }
+
+      template <typename _OutA1, typename _OutA2, typename... _InA>
+      friend bool
+      operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+                 const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept;
+    };
+
+  template <typename _OutA1, typename _OutA2, typename... _InA>
+    inline bool
+    operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+               const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
+    {
+      return __a.outer_allocator() == __b.outer_allocator()
+          && __a._M_inner == __b._M_inner;
+    }
+
+  template <typename _OutA1, typename _OutA2, typename... _InA>
+    inline bool
+    operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
+               const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept
+    { return !(__a == __b); }
+
+  /// @}
+
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace
+
+#endif // __GXX_EXPERIMENTAL_CXX0X__
+
+#endif // _SCOPED_ALLOCATOR
diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/1.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/1.cc
new file mode 100644 (file)
index 0000000..823769f
--- /dev/null
@@ -0,0 +1,99 @@
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 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/>.
+
+#include <memory>
+#include <scoped_allocator>
+#include <vector>
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using __gnu_test::uneq_allocator;
+
+struct Element
+{
+  typedef uneq_allocator<Element> allocator_type;
+
+  allocator_type alloc;
+
+  Element(const allocator_type& a = allocator_type()) : alloc(a) { }
+
+  Element(std::allocator_arg_t, const allocator_type& a, int i = 0)
+  : alloc(a) { }
+
+  Element(std::allocator_arg_t, const allocator_type& a, const Element&)
+  : alloc(a) { }
+
+  const allocator_type& get_allocator() const { return alloc; }
+};
+
+void test01()
+{
+  bool test __attribute((unused)) = false;
+
+  typedef std::scoped_allocator_adaptor<Element::allocator_type> alloc1_type;
+
+  typedef std::vector<Element, alloc1_type> EltVec;
+
+  alloc1_type a1(1);
+  Element e;
+  EltVec ev1(1, e, a1);
+  VERIFY( ev1[0].get_allocator().get_personality() == 1 );
+}
+
+void test02()
+{
+  bool test __attribute((unused)) = false;
+
+  typedef std::vector<Element, Element::allocator_type> EltVec;
+
+  typedef std::scoped_allocator_adaptor<EltVec::allocator_type,
+                                       Element::allocator_type> alloc_type;
+
+  typedef std::vector<EltVec, alloc_type> EltVecVec;
+
+  alloc_type a(1, 2);
+  Element e;
+  EltVec ev(1, e);
+  EltVecVec evv(1, ev, a);
+
+  VERIFY( evv.get_allocator().get_personality() == 1 );
+  VERIFY( evv[0].get_allocator().get_personality() == 2 );
+  VERIFY( evv[0][0].get_allocator().get_personality() == 2 );
+
+  alloc_type a2(3, 4);
+
+  EltVecVec evv2(evv, a2); // copy with a different allocator
+
+  VERIFY( evv2.get_allocator().get_personality() == 3 );
+  VERIFY( evv2[0].get_allocator().get_personality() == 4 );
+  VERIFY( evv2[0][0].get_allocator().get_personality() == 4 );
+
+  EltVecVec evv3(std::move(evv), a2); // move with a different allocator
+
+  VERIFY( evv3.get_allocator().get_personality() == 3 );
+  VERIFY( evv3[0].get_allocator().get_personality() == 4 );
+  VERIFY( evv3[0][0].get_allocator().get_personality() == 4 );
+
+}
+
+
+int main()
+{
+  test01();
+}
diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/propagation.cc
new file mode 100644 (file)
index 0000000..5679b73
--- /dev/null
@@ -0,0 +1,105 @@
+// { dg-do compile }
+// { dg-options "-std=gnu++0x" }
+
+// Copyright (C) 2011 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/>.
+
+// test that propagate_on_container_xxx is true iff it is true for
+// any of the outer or inner allocators
+
+#include <scoped_allocator>
+
+using std::scoped_allocator_adaptor;
+
+typedef short test_type;
+
+template<typename T>
+  struct minimal_allocator
+  {
+    typedef T value_type;
+    minimal_allocator();
+    template <typename U>
+      minimal_allocator(const minimal_allocator<U>&);
+    T* allocate(std::size_t);
+    void deallocate(T*, std::size_t);
+  };
+
+template<typename T, bool copy, bool move, bool swap>
+  struct test_allocator : minimal_allocator<T>
+  {
+    struct propagate_on_container_copy_assignment
+    { static const bool value = copy; };
+
+    struct propagate_on_container_move_assignment
+    { static const bool value = move; };
+
+    struct propagate_on_container_swap
+    { static const bool value = swap; };
+  };
+
+template<typename A>
+  constexpr bool prop_on_copy()
+  {
+    typedef typename A::propagate_on_container_copy_assignment type;
+    return type::value;
+  }
+
+template<typename A>
+  constexpr bool prop_on_move()
+  {
+    typedef typename A::propagate_on_container_move_assignment type;
+    return type::value;
+  }
+
+template<typename A>
+  constexpr bool prop_on_swap()
+  {
+    typedef typename A::propagate_on_container_swap type;
+    return type::value;
+  }
+
+template<typename A, bool C, bool M, bool S>
+  constexpr bool test1()
+  {
+    static_assert( prop_on_copy<A>() == C, "copy" );
+    static_assert( prop_on_move<A>() == M, "move" );
+    static_assert( prop_on_swap<A>() == S, "swap" );
+    return true;
+  }
+
+template<bool C, bool M, bool S>
+  constexpr bool test2()
+  {
+    typedef minimal_allocator<test_type>       base_alloc;
+    typedef test_allocator<test_type, C, M, S> test_alloc;
+    typedef scoped_allocator_adaptor<base_alloc, test_alloc> scoped1;
+    typedef scoped_allocator_adaptor<test_alloc, base_alloc> scoped2;
+    typedef scoped_allocator_adaptor<test_alloc, test_alloc> scoped3;
+    return test1<scoped1, C, M, S>()
+        && test1<scoped2, C, M, S>()
+        && test1<scoped3, C, M, S>();
+  }
+
+static_assert( test2<false, false, false>(), "never propagate" );
+static_assert( test2<true, false, false>(), "propagate on copy" );
+static_assert( test2<false, true, false>(), "propagate on move" );
+static_assert( test2<false, false, true>(), "propagate on swap" );
+static_assert( test2<true, true, false>(), "propagate on copy & move" );
+static_assert( test2<true, false, true>(), "propagate on copy & swap" );
+static_assert( test2<false, true, true>(), "propagate on move & swap" );
+static_assert( test2<true, true, true>(), "always propagate" );
+
diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/explicit_instantiation.cc
new file mode 100644 (file)
index 0000000..1f85756
--- /dev/null
@@ -0,0 +1,47 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+
+// Copyright (C) 2011 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/>.
+
+// NB: This file is for testing memory with NO OTHER INCLUDES.
+
+#include <scoped_allocator>
+#include <memory>
+
+typedef short test_type;
+
+template<typename T>
+  struct minimal_allocator
+  {
+    typedef T value_type;
+    minimal_allocator();
+    template <typename U>
+      minimal_allocator(const minimal_allocator<U>&);
+    T* allocate(unsigned long);
+    void deallocate(T*, unsigned long);
+  };
+
+namespace std
+{
+  template struct scoped_allocator_adaptor<std::allocator<test_type>>;
+
+  template struct scoped_allocator_adaptor<minimal_allocator<test_type>>;
+
+  template struct scoped_allocator_adaptor<std::allocator<test_type>,
+                                           minimal_allocator<test_type>>;
+}
diff --git a/libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/typedefs.cc b/libstdc++-v3/testsuite/20_util/scoped_allocator/requirements/typedefs.cc
new file mode 100644 (file)
index 0000000..762bedf
--- /dev/null
@@ -0,0 +1,67 @@
+// { dg-options "-std=gnu++0x" }
+//
+// Copyright (C) 2011 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/>.
+
+// 
+// NB: This file is for testing scoped_allocator with NO OTHER INCLUDES.
+
+#include <scoped_allocator>
+
+// { dg-do compile }
+
+template<typename T>
+  struct minimal_allocator
+  {
+    typedef T value_type;
+    minimal_allocator();
+    template <typename U>
+      minimal_allocator(const minimal_allocator<U>&);
+    T* allocate(unsigned long);
+    void deallocate(T*, unsigned long);
+  };
+
+struct S
+{
+  typedef minimal_allocator<short> allocator_type;
+  S(const allocator_type&);
+};
+
+void test01()
+{
+  typedef minimal_allocator<S>                      outer_type;
+  typedef minimal_allocator<S::allocator_type>      inner_type;
+  typedef std::scoped_allocator_adaptor<outer_type, inner_type> test_type;
+
+  // Check for required typedefs
+  typedef typename test_type::outer_allocator_type  outer_allocator_type;
+  typedef typename test_type::inner_allocator_type  inner_allocator_type;
+  typedef typename test_type::value_type            value_type;
+  typedef typename test_type::size_type             size_type;
+  typedef typename test_type::difference_type       difference_type;
+  typedef typename test_type::pointer               pointer;
+  typedef typename test_type::const_pointer         const_pointer;
+  typedef typename test_type::void_pointer          void_pointer;
+  typedef typename test_type::const_void_pointer    const_void_pointer;
+  typedef typename test_type::propagate_on_container_copy_assignment
+    propagate_on_container_copy_assignment;
+  typedef typename test_type::propagate_on_container_move_assignment
+    propagate_on_container_move_assignment;
+  typedef typename test_type::propagate_on_container_swap
+    propagate_on_container_swap;
+}
+