scoped_allocator (__outermost_alloc_traits): Define.
* include/std/scoped_allocator (__outermost_alloc_traits): Define. (scoped_allocator_adaptor::destroy): Use it. (scoped_allocator_adaptor::construct): Likewise. Overload for piecewise construction of std::pair objects. * testsuite/20_util/scoped_allocator/2.cc: New. * doc/xml/manual/status_cxx2011.xml: Update. From-SVN: r192613
This commit is contained in:
parent
e665269ada
commit
644b2e4c0d
4 changed files with 412 additions and 21 deletions
|
@ -1,3 +1,12 @@
|
|||
2012-10-19 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
||||
* include/std/scoped_allocator (__outermost_alloc_traits): Define.
|
||||
(scoped_allocator_adaptor::destroy): Use it.
|
||||
(scoped_allocator_adaptor::construct): Likewise. Overload for
|
||||
piecewise construction of std::pair objects.
|
||||
* testsuite/20_util/scoped_allocator/2.cc: New.
|
||||
* doc/xml/manual/status_cxx2011.xml: Update.
|
||||
|
||||
2012-10-18 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
||||
* include/bits/forward_list.h: Add C++11 allocator support.
|
||||
|
|
|
@ -1037,7 +1037,7 @@ particular release.
|
|||
<entry>20.12.4</entry>
|
||||
<entry>Scoped allocator adaptor members</entry>
|
||||
<entry>Partial</entry>
|
||||
<entry>Missing std::pair piecewise construction.</entry>
|
||||
<entry>OUTERMOST is not recursive.</entry>
|
||||
</row>
|
||||
<row>
|
||||
<entry>20.12.5</entry>
|
||||
|
|
|
@ -74,7 +74,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
: allocator_traits<_Alloc>::propagate_on_container_swap
|
||||
{ };
|
||||
|
||||
|
||||
|
||||
template<typename _Alloc>
|
||||
inline auto
|
||||
__do_outermost(_Alloc& __a, _Alloc*) -> decltype(__a.outer_allocator())
|
||||
|
@ -85,6 +85,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__do_outermost(_Alloc& __a, ...)
|
||||
{ return __a; }
|
||||
|
||||
// TODO: make recursive (see note in 20.12.4/1)
|
||||
template<typename _Alloc>
|
||||
inline auto
|
||||
__outermost(_Alloc& __a) -> decltype(__do_outermost(__a, &__a))
|
||||
|
@ -190,15 +191,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_M_tie() const noexcept
|
||||
{ return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); }
|
||||
|
||||
template<typename _Alloc>
|
||||
using __outermost_type = typename
|
||||
std::decay<decltype(__outermost(std::declval<_Alloc&>()))>::type;
|
||||
|
||||
template<typename _Alloc>
|
||||
using __outermost_alloc_traits
|
||||
= allocator_traits<__outermost_type<_Alloc>>;
|
||||
|
||||
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 __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||
_O_traits::construct(__outermost(*this), __p,
|
||||
std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
typedef __uses_alloc1<typename __inner_type::__type> __uses_alloc1_;
|
||||
|
@ -208,22 +215,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
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)...);
|
||||
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||
_O_traits::construct(__outermost(*this), __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());
|
||||
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||
_O_traits::construct(__outermost(*this), __p,
|
||||
std::forward<_Args>(__args)...,
|
||||
inner_allocator());
|
||||
}
|
||||
|
||||
template<typename _Alloc>
|
||||
|
@ -338,15 +343,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
|
||||
}
|
||||
|
||||
// TODO: construct pairs
|
||||
template<typename _T1, typename _T2, typename... _Args1,
|
||||
typename... _Args2>
|
||||
void
|
||||
construct(pair<_T1, _T2>* __p, piecewise_construct_t,
|
||||
tuple<_Args1...> __x, tuple<_Args2...> __y)
|
||||
{
|
||||
auto& __inner = inner_allocator();
|
||||
auto __x_use_tag
|
||||
= __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner);
|
||||
auto __y_use_tag
|
||||
= __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner);
|
||||
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||
_O_traits::construct(__outermost(*this), __p, piecewise_construct,
|
||||
_M_construct_p(__x_use_tag, __x),
|
||||
_M_construct_p(__y_use_tag, __y));
|
||||
}
|
||||
|
||||
template<typename _T1, typename _T2>
|
||||
void
|
||||
construct(pair<_T1, _T2>* __p)
|
||||
{ construct(__p, piecewise_construct, tuple<>(), tuple<>()); }
|
||||
|
||||
template<typename _T1, typename _T2, typename _U, typename _V>
|
||||
void
|
||||
construct(pair<_T1, _T2>* __p, _U&& __u, _V&& __v)
|
||||
{
|
||||
construct(__p, piecewise_construct,
|
||||
std::forward_as_tuple(std::forward<_U>(__u)),
|
||||
std::forward_as_tuple(std::forward<_V>(__v)));
|
||||
}
|
||||
|
||||
template<typename _T1, typename _T2, typename _U, typename _V>
|
||||
void
|
||||
construct(pair<_T1, _T2>* __p, const pair<_U, _V>& __x)
|
||||
{
|
||||
construct(__p, piecewise_construct,
|
||||
std::forward_as_tuple(__x.first),
|
||||
std::forward_as_tuple(__x.second));
|
||||
}
|
||||
|
||||
template<typename _T1, typename _T2, typename _U, typename _V>
|
||||
void
|
||||
construct(pair<_T1, _T2>* __p, pair<_U, _V>&& __x)
|
||||
{
|
||||
construct(__p, piecewise_construct,
|
||||
std::forward_as_tuple(std::forward<_U>(__x.first)),
|
||||
std::forward_as_tuple(std::forward<_V>(__x.second)));
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||
_O_traits::destroy(__outermost(*this), __p);
|
||||
}
|
||||
|
||||
scoped_allocator_adaptor
|
||||
select_on_container_copy_construction() const
|
||||
|
@ -360,6 +411,29 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
friend bool
|
||||
operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a,
|
||||
const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept;
|
||||
|
||||
private:
|
||||
template<typename _Tuple>
|
||||
_Tuple&&
|
||||
_M_construct_p(__uses_alloc0, _Tuple& __t)
|
||||
{ return std::move(__t); }
|
||||
|
||||
template<typename... _Args>
|
||||
std::tuple<allocator_arg_t, inner_allocator_type&, _Args...>
|
||||
_M_construct_p(__uses_alloc1_, std::tuple<_Args...>& __t)
|
||||
{
|
||||
typedef std::tuple<allocator_arg_t, inner_allocator_type&> _Tuple;
|
||||
return std::tuple_cat(_Tuple(allocator_arg, inner_allocator()),
|
||||
std::move(__t));
|
||||
}
|
||||
|
||||
template<typename... _Args>
|
||||
std::tuple<_Args..., inner_allocator_type&>
|
||||
_M_construct_p(__uses_alloc2_, std::tuple<_Args...>& __t)
|
||||
{
|
||||
typedef std::tuple<inner_allocator_type&> _Tuple;
|
||||
return std::tuple_cat(std::move(__t), _Tuple(inner_allocator()));
|
||||
}
|
||||
};
|
||||
|
||||
template <typename _OutA1, typename _OutA2, typename... _InA>
|
||||
|
|
308
libstdc++-v3/testsuite/20_util/scoped_allocator/2.cc
Normal file
308
libstdc++-v3/testsuite/20_util/scoped_allocator/2.cc
Normal file
|
@ -0,0 +1,308 @@
|
|||
// { dg-options "-std=gnu++0x" }
|
||||
|
||||
// Copyright (C) 2012 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>
|
||||
|
||||
// 20.12.4 Scoped allocator adaptor members [allocator.adaptor.members]
|
||||
//
|
||||
// Test piecewise construction of std::pair by scoped_allocator_adaptor
|
||||
|
||||
using __gnu_test::uneq_allocator;
|
||||
using std::scoped_allocator_adaptor;
|
||||
|
||||
// a DefaultConstructible and CopyConstructible type
|
||||
struct def
|
||||
{
|
||||
def() : id(999) { }
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
// a CopyConstructible and non-DefaultConstructible type
|
||||
struct copyable
|
||||
{
|
||||
copyable(int id) : id(id) { }
|
||||
|
||||
// not constructed with an allocator so nothing to test
|
||||
bool verify() const { return true; }
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
// a MoveConstructible and non-DefaultConstructible type
|
||||
struct move_only
|
||||
{
|
||||
move_only(int id) : id(id) { }
|
||||
move_only(move_only&&) = default;
|
||||
|
||||
// not constructed with an allocator so nothing to test
|
||||
bool verify() const { return true; }
|
||||
|
||||
int id;
|
||||
};
|
||||
|
||||
// a type for which std::uses_allocator is true
|
||||
struct uses_alloc_post
|
||||
{
|
||||
typedef uneq_allocator<uses_alloc_post> allocator_type;
|
||||
|
||||
uses_alloc_post(const allocator_type& alloc)
|
||||
: allocator_personality(alloc.get_personality()), id(999)
|
||||
{ }
|
||||
|
||||
uses_alloc_post(copyable arg, const allocator_type& alloc)
|
||||
: allocator_personality(alloc.get_personality()), id(arg.id)
|
||||
{ }
|
||||
|
||||
uses_alloc_post(move_only arg, const allocator_type& alloc)
|
||||
: allocator_personality(alloc.get_personality()), id(arg.id)
|
||||
{ }
|
||||
|
||||
// allocator-extended copy ctor
|
||||
uses_alloc_post(const uses_alloc_post& other, const allocator_type& alloc)
|
||||
: allocator_personality(alloc.get_personality()), id(other.id)
|
||||
{ }
|
||||
|
||||
// verify we were constructed with right allocator
|
||||
bool verify() const { return allocator_personality == id; }
|
||||
|
||||
int allocator_personality;
|
||||
int id;
|
||||
};
|
||||
|
||||
// a type for which std::uses_allocator is true
|
||||
struct uses_alloc_pre : uses_alloc_post
|
||||
{
|
||||
typedef uneq_allocator<uses_alloc_pre> allocator_type;
|
||||
|
||||
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc)
|
||||
: uses_alloc_post(alloc)
|
||||
{ }
|
||||
|
||||
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
|
||||
copyable arg)
|
||||
: uses_alloc_post(arg, alloc)
|
||||
{ }
|
||||
|
||||
// allocator-extended copy ctor
|
||||
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
|
||||
const uses_alloc_pre& other)
|
||||
: uses_alloc_post(other, alloc)
|
||||
{ }
|
||||
|
||||
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
|
||||
move_only arg)
|
||||
: uses_alloc_post(std::move(arg), alloc)
|
||||
{ }
|
||||
};
|
||||
|
||||
template<typename A, typename B>
|
||||
void
|
||||
test_def()
|
||||
{
|
||||
bool test __attribute((unused)) = false;
|
||||
|
||||
typedef std::pair<A, B> test_type;
|
||||
typedef uneq_allocator<test_type> alloc_type;
|
||||
typedef scoped_allocator_adaptor<alloc_type, alloc_type> alloc_adaptor;
|
||||
|
||||
int inner_id = 2;
|
||||
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
|
||||
|
||||
// all pair members that can be constructed with an allocator
|
||||
// should be constructed with the inner allocator, with personality==2
|
||||
|
||||
auto p = a.allocate(1);
|
||||
|
||||
// construct(pair<T1, T2>* p, piecewise_construct_t, tuple<...>, tuple<...>)
|
||||
std::tuple<> t;
|
||||
a.construct(p, std::piecewise_construct, t, t);
|
||||
VERIFY( p->first.id == 999 );
|
||||
VERIFY( p->second.id == 999 );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* __p)
|
||||
a.construct(p);
|
||||
VERIFY( p->first.id == 999 );
|
||||
VERIFY( p->second.id == 999 );
|
||||
auto pp = *p;
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* p, const pair<U, V>& x)
|
||||
a.construct(p, pp);
|
||||
VERIFY( p->first.id == 999 );
|
||||
VERIFY( p->second.id == 999 );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* p, pair<U, V>&& x)
|
||||
a.construct(p, std::move(pp));
|
||||
VERIFY( p->first.id == 999 );
|
||||
VERIFY( p->second.id == 999 );
|
||||
a.destroy(p);
|
||||
|
||||
a.deallocate(p, 1);
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
void
|
||||
test_copying()
|
||||
{
|
||||
bool test __attribute((unused)) = false;
|
||||
|
||||
typedef std::pair<A, B> test_type;
|
||||
typedef uneq_allocator<test_type> alloc_type;
|
||||
typedef scoped_allocator_adaptor<alloc_type, alloc_type> alloc_adaptor;
|
||||
|
||||
int inner_id = 2;
|
||||
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
|
||||
|
||||
// all pair members that can be constructed with an allocator
|
||||
// should be constructed with the inner allocator, with personality==2
|
||||
|
||||
auto p = a.allocate(1);
|
||||
|
||||
// construct(pair<T1, T2>* p, piecewise_construct_t, tuple<...>, tuple<...>)
|
||||
auto t = std::make_tuple(copyable(inner_id));
|
||||
a.construct(p, std::piecewise_construct, t, t);
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* __p)
|
||||
// cannot test this overload using non-DefaultConstructible types
|
||||
|
||||
// construct(pair<T1, T2>* p, U&& x, V&& y)
|
||||
copyable c(inner_id);
|
||||
a.construct(p, c, c);
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
auto pp = *p;
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* p, const pair<U, V>& x)
|
||||
a.construct(p, pp);
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* p, pair<U, V>&& x)
|
||||
a.construct(p, std::move(pp));
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
a.deallocate(p, 1);
|
||||
}
|
||||
|
||||
template<typename A, typename B>
|
||||
void
|
||||
test_moving()
|
||||
{
|
||||
bool test __attribute((unused)) = false;
|
||||
|
||||
typedef std::pair<A, B> test_type;
|
||||
typedef uneq_allocator<test_type> alloc_type;
|
||||
typedef scoped_allocator_adaptor<alloc_type, alloc_type> alloc_adaptor;
|
||||
|
||||
int inner_id = 2;
|
||||
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
|
||||
|
||||
// all pair members that can be constructed with an allocator
|
||||
// should be constructed with the inner allocator, with personality==2
|
||||
|
||||
auto p = a.allocate(1);
|
||||
|
||||
// construct(pair<T1, T2>* p, piecewise_construct_t, tuple<...>, tuple<...>)
|
||||
a.construct(p, std::piecewise_construct,
|
||||
std::make_tuple(move_only(inner_id)),
|
||||
std::make_tuple(move_only(inner_id)));
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* __p)
|
||||
// cannot test this overload using non-DefaultConstructible types
|
||||
|
||||
// construct(pair<T1, T2>* p, U&& x, V&& y)
|
||||
a.construct(p, move_only(inner_id), move_only(inner_id));
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
// construct(pair<T1, T2>* p, const pair<U, V>& x)
|
||||
// cannot test this overload using move-only types
|
||||
|
||||
// construct(pair<T1, T2>* p, pair<U, V>&& x)
|
||||
a.construct(p, std::make_pair(move_only(inner_id), move_only(inner_id)));
|
||||
VERIFY( p->first.verify() );
|
||||
VERIFY( p->second.verify() );
|
||||
a.destroy(p);
|
||||
|
||||
a.deallocate(p, 1);
|
||||
}
|
||||
|
||||
void test01()
|
||||
{
|
||||
test_def<def, def>();
|
||||
test_def<def, uses_alloc_pre>();
|
||||
test_def<def, uses_alloc_post>();
|
||||
test_def<uses_alloc_pre, def>();
|
||||
test_def<uses_alloc_pre, uses_alloc_pre>();
|
||||
test_def<uses_alloc_pre, uses_alloc_post>();
|
||||
test_def<uses_alloc_post, def>();
|
||||
test_def<uses_alloc_post, uses_alloc_pre>();
|
||||
test_def<uses_alloc_post, uses_alloc_post>();
|
||||
}
|
||||
|
||||
void test02()
|
||||
{
|
||||
test_copying<copyable, copyable>();
|
||||
test_copying<copyable, uses_alloc_pre>();
|
||||
test_copying<copyable, uses_alloc_post>();
|
||||
test_copying<uses_alloc_pre, copyable>();
|
||||
test_copying<uses_alloc_pre, uses_alloc_pre>();
|
||||
test_copying<uses_alloc_pre, uses_alloc_post>();
|
||||
test_copying<uses_alloc_post, copyable>();
|
||||
test_copying<uses_alloc_post, uses_alloc_pre>();
|
||||
test_copying<uses_alloc_post, uses_alloc_post>();
|
||||
}
|
||||
|
||||
void test03()
|
||||
{
|
||||
test_moving<move_only, move_only>();
|
||||
test_moving<move_only, uses_alloc_pre>();
|
||||
test_moving<move_only, uses_alloc_post>();
|
||||
test_moving<uses_alloc_pre, move_only>();
|
||||
test_moving<uses_alloc_pre, uses_alloc_pre>();
|
||||
test_moving<uses_alloc_pre, uses_alloc_post>();
|
||||
test_moving<uses_alloc_post, move_only>();
|
||||
test_moving<uses_alloc_post, uses_alloc_pre>();
|
||||
test_moving<uses_alloc_post, uses_alloc_post>();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
test01();
|
||||
test02();
|
||||
test03();
|
||||
}
|
Loading…
Add table
Reference in a new issue