Refactor uses-allocator construction
Remove duplicated logic in experimental::pmr::polymorphic_allocator by calling the __uses_allocator_construct helper. Fix bugs in std::pmr::polymorphic_allocator with incorrect SFINAE constraint and incorrect argument order. * include/bits/uses_allocator.h (__uses_allocator_construct): Qualify calls to __uses_allocator_construct_impl and __use_alloc. * include/experimental/memory_resource (polymorphic_allocator::_M_construct): Remove. (polymorphic_allocator::construct): Call __uses_allocator_construct. Qualify calls to __use_alloc. * include/std/memory_resource (polymorphic_allocator::construct): Fix type in SFINAE constraint. Use constexpr if instead of tag dispatching to _S_construct overloads. (polymorphic_allocator::construct(pair<T1, T2>*, ...)): Fix order of arguments to _S_construct_p. (polymorphic_allocator::_S_construct): Remove. (polymorphic_allocator::_S_construct_p): Return allocators by value not by reference. * include/std/scoped_allocator (scoped_allocator_adaptor::construct): Qualify calls to __use_alloc. * testsuite/20_util/polymorphic_allocator/construct_pair.cc: New test, copied from testsuite/20_util/scoped_allocator/construct_pair.cc. * testsuite/experimental/polymorphic_allocator/1.cc: New test. * testsuite/experimental/polymorphic_allocator/construct_pair.cc: New test. From-SVN: r263566
This commit is contained in:
parent
96e6ae576c
commit
b479fbad24
@ -1,5 +1,27 @@
|
|||||||
2018-08-15 Jonathan Wakely <jwakely@redhat.com>
|
2018-08-15 Jonathan Wakely <jwakely@redhat.com>
|
||||||
|
|
||||||
|
* include/bits/uses_allocator.h (__uses_allocator_construct): Qualify
|
||||||
|
calls to __uses_allocator_construct_impl and __use_alloc.
|
||||||
|
* include/experimental/memory_resource
|
||||||
|
(polymorphic_allocator::_M_construct): Remove.
|
||||||
|
(polymorphic_allocator::construct): Call __uses_allocator_construct.
|
||||||
|
Qualify calls to __use_alloc.
|
||||||
|
* include/std/memory_resource (polymorphic_allocator::construct): Fix
|
||||||
|
type in SFINAE constraint. Use constexpr if instead of tag dispatching
|
||||||
|
to _S_construct overloads.
|
||||||
|
(polymorphic_allocator::construct(pair<T1, T2>*, ...)): Fix order of
|
||||||
|
arguments to _S_construct_p.
|
||||||
|
(polymorphic_allocator::_S_construct): Remove.
|
||||||
|
(polymorphic_allocator::_S_construct_p): Return allocators by value
|
||||||
|
not by reference.
|
||||||
|
* include/std/scoped_allocator (scoped_allocator_adaptor::construct):
|
||||||
|
Qualify calls to __use_alloc.
|
||||||
|
* testsuite/20_util/polymorphic_allocator/construct_pair.cc: New test,
|
||||||
|
copied from testsuite/20_util/scoped_allocator/construct_pair.cc.
|
||||||
|
* testsuite/experimental/polymorphic_allocator/1.cc: New test.
|
||||||
|
* testsuite/experimental/polymorphic_allocator/construct_pair.cc:
|
||||||
|
New test.
|
||||||
|
|
||||||
* src/c++17/memory_resource.cc [!_GLIBCXX_HAS_GTHREADS]
|
* src/c++17/memory_resource.cc [!_GLIBCXX_HAS_GTHREADS]
|
||||||
(atomic_mem_res): Add unsynchronized definition for single-threaded.
|
(atomic_mem_res): Add unsynchronized definition for single-threaded.
|
||||||
|
|
||||||
|
@ -179,8 +179,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
|
void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr,
|
||||||
_Args&&... __args)
|
_Args&&... __args)
|
||||||
{
|
{
|
||||||
__uses_allocator_construct_impl(__use_alloc<_Tp, _Alloc, _Args...>(__a),
|
std::__uses_allocator_construct_impl(
|
||||||
__ptr, std::forward<_Args>(__args)...);
|
std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
_GLIBCXX_END_NAMESPACE_VERSION
|
_GLIBCXX_END_NAMESPACE_VERSION
|
||||||
|
@ -123,27 +123,6 @@ namespace pmr {
|
|||||||
template<typename _Tp>
|
template<typename _Tp>
|
||||||
class polymorphic_allocator
|
class polymorphic_allocator
|
||||||
{
|
{
|
||||||
using __uses_alloc1_ = __uses_alloc1<memory_resource*>;
|
|
||||||
using __uses_alloc2_ = __uses_alloc2<memory_resource*>;
|
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
void
|
|
||||||
_M_construct(__uses_alloc0, _Tp1* __p, _Args&&... __args)
|
|
||||||
{ ::new(__p) _Tp1(std::forward<_Args>(__args)...); }
|
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
void
|
|
||||||
_M_construct(__uses_alloc1_, _Tp1* __p, _Args&&... __args)
|
|
||||||
{
|
|
||||||
::new(__p) _Tp1(allocator_arg, this->resource(),
|
|
||||||
std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
void
|
|
||||||
_M_construct(__uses_alloc2_, _Tp1* __p, _Args&&... __args)
|
|
||||||
{ ::new(__p) _Tp1(std::forward<_Args>(__args)..., this->resource()); }
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using value_type = _Tp;
|
using value_type = _Tp;
|
||||||
|
|
||||||
@ -178,10 +157,8 @@ namespace pmr {
|
|||||||
void
|
void
|
||||||
construct(_Tp1* __p, _Args&&... __args)
|
construct(_Tp1* __p, _Args&&... __args)
|
||||||
{
|
{
|
||||||
memory_resource* const __resource = this->resource();
|
std::__uses_allocator_construct(this->resource(), __p,
|
||||||
auto __use_tag
|
std::forward<_Args>(__args)...);
|
||||||
= __use_alloc<_Tp1, memory_resource*, _Args...>(__resource);
|
|
||||||
_M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Specializations for pair using piecewise construction
|
// Specializations for pair using piecewise construction
|
||||||
@ -193,9 +170,9 @@ namespace pmr {
|
|||||||
{
|
{
|
||||||
memory_resource* const __resource = this->resource();
|
memory_resource* const __resource = this->resource();
|
||||||
auto __x_use_tag =
|
auto __x_use_tag =
|
||||||
__use_alloc<_Tp1, memory_resource*, _Args1...>(__resource);
|
std::__use_alloc<_Tp1, memory_resource*, _Args1...>(__resource);
|
||||||
auto __y_use_tag =
|
auto __y_use_tag =
|
||||||
__use_alloc<_Tp2, memory_resource*, _Args2...>(__resource);
|
std::__use_alloc<_Tp2, memory_resource*, _Args2...>(__resource);
|
||||||
|
|
||||||
::new(__p) std::pair<_Tp1, _Tp2>(piecewise_construct,
|
::new(__p) std::pair<_Tp1, _Tp2>(piecewise_construct,
|
||||||
_M_construct_p(__x_use_tag, __x),
|
_M_construct_p(__x_use_tag, __x),
|
||||||
@ -247,6 +224,9 @@ namespace pmr {
|
|||||||
memory_resource* resource() const { return _M_resource; }
|
memory_resource* resource() const { return _M_resource; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using __uses_alloc1_ = __uses_alloc1<memory_resource*>;
|
||||||
|
using __uses_alloc2_ = __uses_alloc2<memory_resource*>;
|
||||||
|
|
||||||
template<typename _Tuple>
|
template<typename _Tuple>
|
||||||
_Tuple&&
|
_Tuple&&
|
||||||
_M_construct_p(__uses_alloc0, _Tuple& __t)
|
_M_construct_p(__uses_alloc0, _Tuple& __t)
|
||||||
|
@ -163,14 +163,20 @@ namespace pmr
|
|||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
template<typename _Tp1, typename... _Args>
|
||||||
__attribute__((__nonnull__))
|
__attribute__((__nonnull__))
|
||||||
typename __not_pair<_Tp>::type
|
typename __not_pair<_Tp1>::type
|
||||||
construct(_Tp1* __p, _Args&&... __args)
|
construct(_Tp1* __p, _Args&&... __args)
|
||||||
{
|
{
|
||||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||||
// 2969. polymorphic_allocator::construct() shouldn't pass resource()
|
// 2969. polymorphic_allocator::construct() shouldn't pass resource()
|
||||||
auto __use_tag
|
using __use_tag
|
||||||
= __use_alloc<_Tp1, polymorphic_allocator, _Args...>(*this);
|
= std::__uses_alloc_t<_Tp1, polymorphic_allocator, _Args...>;
|
||||||
_S_construct(__use_tag, __p, std::forward<_Args>(__args)...);
|
if constexpr (is_base_of_v<__uses_alloc0, __use_tag>)
|
||||||
|
::new(__p) _Tp1(std::forward<_Args>(__args)...);
|
||||||
|
else if constexpr (is_base_of_v<__uses_alloc1_, __use_tag>)
|
||||||
|
::new(__p) _Tp1(allocator_arg, *this,
|
||||||
|
std::forward<_Args>(__args)...);
|
||||||
|
else
|
||||||
|
::new(__p) _Tp1(std::forward<_Args>(__args)..., *this);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1, typename _Tp2,
|
template<typename _Tp1, typename _Tp2,
|
||||||
@ -188,8 +194,8 @@ namespace pmr
|
|||||||
index_sequence_for<_Args2...> __y_i;
|
index_sequence_for<_Args2...> __y_i;
|
||||||
|
|
||||||
::new(__p) pair<_Tp1, _Tp2>(piecewise_construct,
|
::new(__p) pair<_Tp1, _Tp2>(piecewise_construct,
|
||||||
_S_construct_p(__x_tag, __x, __x_i),
|
_S_construct_p(__x_tag, __x_i, __x),
|
||||||
_S_construct_p(__y_tag, __y, __y_i));
|
_S_construct_p(__y_tag, __y_i, __y));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename _Tp1, typename _Tp2>
|
template<typename _Tp1, typename _Tp2>
|
||||||
@ -247,31 +253,13 @@ namespace pmr
|
|||||||
using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>;
|
using __uses_alloc1_ = __uses_alloc1<polymorphic_allocator>;
|
||||||
using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
|
using __uses_alloc2_ = __uses_alloc2<polymorphic_allocator>;
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
static void
|
|
||||||
_S_construct(__uses_alloc0, _Tp1* __p, _Args&&... __args)
|
|
||||||
{ ::new(__p) _Tp1(std::forward<_Args>(__args)...); }
|
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
static void
|
|
||||||
_S_construct(__uses_alloc1_ __ua, _Tp1* __p, _Args&&... __args)
|
|
||||||
{
|
|
||||||
::new(__p) _Tp1(allocator_arg, *__ua._M_a,
|
|
||||||
std::forward<_Args>(__args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename _Tp1, typename... _Args>
|
|
||||||
static void
|
|
||||||
_S_construct(__uses_alloc2_ __ua, _Tp1* __p, _Args&&... __args)
|
|
||||||
{ ::new(__p) _Tp1(std::forward<_Args>(__args)..., *__ua._M_a); }
|
|
||||||
|
|
||||||
template<typename _Ind, typename... _Args>
|
template<typename _Ind, typename... _Args>
|
||||||
static tuple<_Args&&...>
|
static tuple<_Args&&...>
|
||||||
_S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t)
|
_S_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t)
|
||||||
{ return std::move(__t); }
|
{ return std::move(__t); }
|
||||||
|
|
||||||
template<size_t... _Ind, typename... _Args>
|
template<size_t... _Ind, typename... _Args>
|
||||||
static tuple<allocator_arg_t, polymorphic_allocator&, _Args&&...>
|
static tuple<allocator_arg_t, polymorphic_allocator, _Args&&...>
|
||||||
_S_construct_p(__uses_alloc1_ __ua, index_sequence<_Ind...>,
|
_S_construct_p(__uses_alloc1_ __ua, index_sequence<_Ind...>,
|
||||||
tuple<_Args...>& __t)
|
tuple<_Args...>& __t)
|
||||||
{
|
{
|
||||||
@ -281,7 +269,7 @@ namespace pmr
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t... _Ind, typename... _Args>
|
template<size_t... _Ind, typename... _Args>
|
||||||
static tuple<_Args&&..., polymorphic_allocator&>
|
static tuple<_Args&&..., polymorphic_allocator>
|
||||||
_S_construct_p(__uses_alloc2_ __ua, index_sequence<_Ind...>,
|
_S_construct_p(__uses_alloc2_ __ua, index_sequence<_Ind...>,
|
||||||
tuple<_Args...>& __t)
|
tuple<_Args...>& __t)
|
||||||
{ return { std::get<_Ind>(std::move(__t))..., *__ua._M_a }; }
|
{ return { std::get<_Ind>(std::move(__t))..., *__ua._M_a }; }
|
||||||
|
@ -361,7 +361,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
{
|
{
|
||||||
auto& __inner = inner_allocator();
|
auto& __inner = inner_allocator();
|
||||||
auto __use_tag
|
auto __use_tag
|
||||||
= __use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
|
= std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner);
|
||||||
_M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
|
_M_construct(__use_tag, __p, std::forward<_Args>(__args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,9 +375,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||||||
// 2203. wrong argument types for piecewise construction
|
// 2203. wrong argument types for piecewise construction
|
||||||
auto& __inner = inner_allocator();
|
auto& __inner = inner_allocator();
|
||||||
auto __x_use_tag
|
auto __x_use_tag
|
||||||
= __use_alloc<_T1, inner_allocator_type, _Args1...>(__inner);
|
= std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner);
|
||||||
auto __y_use_tag
|
auto __y_use_tag
|
||||||
= __use_alloc<_T2, inner_allocator_type, _Args2...>(__inner);
|
= std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner);
|
||||||
typename _Build_index_tuple<sizeof...(_Args1)>::__type __x_indices;
|
typename _Build_index_tuple<sizeof...(_Args1)>::__type __x_indices;
|
||||||
typename _Build_index_tuple<sizeof...(_Args2)>::__type __y_indices;
|
typename _Build_index_tuple<sizeof...(_Args2)>::__type __y_indices;
|
||||||
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
typedef __outermost_alloc_traits<scoped_allocator_adaptor> _O_traits;
|
||||||
|
@ -0,0 +1,110 @@
|
|||||||
|
// Copyright (C) 2016-2018 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-options "-std=gnu++17" }
|
||||||
|
// { dg-do run { target c++17 } }
|
||||||
|
|
||||||
|
#include <memory_resource>
|
||||||
|
#include <utility>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
struct do_not_copy {
|
||||||
|
do_not_copy() = default;
|
||||||
|
do_not_copy(const do_not_copy&) { throw 1; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
test01()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
X(do_not_copy&&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<do_not_copy>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test02()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
using allocator_type = std::pmr::polymorphic_allocator<int>;
|
||||||
|
X(do_not_copy&&, const allocator_type&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<do_not_copy>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test03()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
using allocator_type = std::pmr::polymorphic_allocator<int>;
|
||||||
|
X(std::allocator_arg_t, const allocator_type&, do_not_copy&&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<do_not_copy>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test04()
|
||||||
|
{
|
||||||
|
struct X
|
||||||
|
{
|
||||||
|
using allocator_type = std::pmr::polymorphic_allocator<int>;
|
||||||
|
X() = default;
|
||||||
|
X(const X&) { throw 1; }
|
||||||
|
X(const X&, const allocator_type&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Y
|
||||||
|
{
|
||||||
|
using allocator_type = std::pmr::polymorphic_allocator<int>;
|
||||||
|
Y() = default;
|
||||||
|
Y(const Y&) = delete;
|
||||||
|
Y(std::allocator_arg_t, const allocator_type&, const Y&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair_type = std::pair<X, Y>;
|
||||||
|
std::pmr::polymorphic_allocator<pair_type> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
/* not const */ pair_type p;
|
||||||
|
a.construct(ptr, p); // LWG 2975
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
|
test04();
|
||||||
|
}
|
@ -0,0 +1,37 @@
|
|||||||
|
// Copyright (C) 2018 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/memory_resource>
|
||||||
|
|
||||||
|
struct X { int i = 0; };
|
||||||
|
|
||||||
|
using test_type = std::experimental::pmr::polymorphic_allocator<X>;
|
||||||
|
|
||||||
|
static_assert(std::is_default_constructible<test_type>{}, "");
|
||||||
|
static_assert(std::is_destructible<test_type>{}, "");
|
||||||
|
static_assert(std::is_copy_constructible<test_type>{}, "");
|
||||||
|
// N.B. std::pmr::polymorphic_allocator is not assignable, see p0337r0
|
||||||
|
static_assert(std::is_copy_assignable<test_type>{}, "");
|
||||||
|
static_assert(std::is_constructible<test_type,
|
||||||
|
std::experimental::pmr::memory_resource*>{}, "");
|
||||||
|
|
||||||
|
static_assert(std::is_same<test_type::value_type, X>{}, "");
|
||||||
|
|
||||||
|
static_assert(!std::is_polymorphic<test_type>{}, "");
|
||||||
|
static_assert(!std::is_final<test_type>{}, "");
|
@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (C) 2018 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 run { target c++14 } }
|
||||||
|
|
||||||
|
#include <experimental/memory_resource>
|
||||||
|
#include <utility>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
struct A { };
|
||||||
|
|
||||||
|
void
|
||||||
|
test01()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
X(A&&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::experimental::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<A>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test02()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
using allocator_type = std::experimental::pmr::polymorphic_allocator<int>;
|
||||||
|
X(A&&, const allocator_type&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::experimental::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<A>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
test03()
|
||||||
|
{
|
||||||
|
struct X {
|
||||||
|
using allocator_type = std::experimental::pmr::polymorphic_allocator<int>;
|
||||||
|
X(std::allocator_arg_t, const allocator_type&, A&&) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
using pair = std::pair<X, int>;
|
||||||
|
std::experimental::pmr::polymorphic_allocator<pair> a;
|
||||||
|
auto ptr = a.allocate(1);
|
||||||
|
a.construct(ptr, std::piecewise_construct,
|
||||||
|
std::tuple<A>{}, std::make_tuple(1));
|
||||||
|
a.deallocate(ptr, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
test01();
|
||||||
|
test02();
|
||||||
|
test03();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user