#include <cstdint>
#if __cplusplus > 201703L
# include <bit> // for ispow2
+# include <new> // for placement operator new
+# include <tuple> // for tuple, make_tuple, make_from_tuple
#endif
namespace std _GLIBCXX_VISIBILITY(default)
{
}
#endif // C++2a
+#if __cplusplus > 201703L
+ template<typename _Tp>
+ struct __is_pair : false_type { };
+ template<typename _Tp, typename _Up>
+ struct __is_pair<pair<_Tp, _Up>> : true_type { };
+ template<typename _Tp, typename _Up>
+ struct __is_pair<const pair<_Tp, _Up>> : true_type { };
+
+ template<typename _Tp, typename __ = _Require<__not_<__is_pair<_Tp>>>,
+ typename _Alloc, typename... _Args>
+ constexpr auto
+ __uses_alloc_args(const _Alloc& __a, _Args&&... __args) noexcept
+ {
+ if constexpr (uses_allocator_v<remove_cv_t<_Tp>, _Alloc>)
+ {
+ if constexpr (is_constructible_v<_Tp, allocator_arg_t,
+ const _Alloc&, _Args...>)
+ {
+ return tuple<allocator_arg_t, const _Alloc&, _Args&&...>(
+ allocator_arg, __a, std::forward<_Args>(__args)...);
+ }
+ else
+ {
+ static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>);
+
+ return tuple<_Args&&..., const _Alloc&>(
+ std::forward<_Args>(__args)..., __a);
+ }
+ }
+ else
+ {
+ static_assert(is_constructible_v<_Tp, _Args...>);
+
+ return tuple<_Args&&...>(std::forward<_Args>(__args)...);
+ }
+ }
+
+#if __cpp_concepts
+ template<typename _Tp>
+ concept bool _Std_pair = __is_pair<_Tp>::value;
+#endif
+
+// This is a temporary workaround until -fconcepts is implied by -std=gnu++2a
+#if __cpp_concepts
+# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) _Std_pair T
+# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) _Std_pair T
+#else
+# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) \
+ typename T, typename __ = _Require<__is_pair<T>>
+# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) typename T, typename
+#endif
+
+ template<typename _Tp,
+#if ! __cpp_concepts
+ typename __ = _Require<__not_<__is_pair<_Tp>>>,
+#endif
+ typename _Alloc, typename... _Args>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a,
+ _Args&&... __args) noexcept
+#if __cpp_concepts
+ requires ! _Std_pair<_Tp>
+#endif
+ {
+ return std::__uses_alloc_args<_Tp>(__a, std::forward<_Args>(__args)...);
+ }
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc,
+ typename _Tuple1, typename _Tuple2>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t,
+ _Tuple1&& __x, _Tuple2&& __y) noexcept;
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc&) noexcept;
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept;
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc&,
+ const pair<_Up, _Vp>&) noexcept;
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept;
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc,
+ typename _Tuple1, typename _Tuple2>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t,
+ _Tuple1&& __x, _Tuple2&& __y) noexcept
+ {
+ using _Tp1 = typename _Tp::first_type;
+ using _Tp2 = typename _Tp::second_type;
+
+ return std::make_tuple(piecewise_construct,
+ std::apply([&__a](auto&&... __args1) {
+ return std::uses_allocator_construction_args<_Tp1>(
+ __a, std::forward<decltype(__args1)>(__args1)...);
+ }, std::forward<_Tuple1>(__x)),
+ std::apply([&__a](auto&&... __args2) {
+ return std::uses_allocator_construction_args<_Tp2>(
+ __a, std::forward<decltype(__args2)>(__args2)...);
+ }, std::forward<_Tuple2>(__y)));
+ }
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a) noexcept
+ {
+ using _Tp1 = typename _Tp::first_type;
+ using _Tp2 = typename _Tp::second_type;
+
+ return std::make_tuple(piecewise_construct,
+ std::uses_allocator_construction_args<_Tp1>(__a),
+ std::uses_allocator_construction_args<_Tp2>(__a));
+ }
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v)
+ noexcept
+ {
+ using _Tp1 = typename _Tp::first_type;
+ using _Tp2 = typename _Tp::second_type;
+
+ return std::make_tuple(piecewise_construct,
+ std::uses_allocator_construction_args<_Tp1>(__a,
+ std::forward<_Up>(__u)),
+ std::uses_allocator_construction_args<_Tp2>(__a,
+ std::forward<_Vp>(__v)));
+ }
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a,
+ const pair<_Up, _Vp>& __pr) noexcept
+ {
+ using _Tp1 = typename _Tp::first_type;
+ using _Tp2 = typename _Tp::second_type;
+
+ return std::make_tuple(piecewise_construct,
+ std::uses_allocator_construction_args<_Tp1>(__a, __pr.first),
+ std::uses_allocator_construction_args<_Tp2>(__a, __pr.second));
+ }
+
+ template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc,
+ typename _Up, typename _Vp>
+ constexpr auto
+ uses_allocator_construction_args(const _Alloc& __a,
+ pair<_Up, _Vp>&& __pr) noexcept
+ {
+ using _Tp1 = typename _Tp::first_type;
+ using _Tp2 = typename _Tp::second_type;
+
+ return std::make_tuple(piecewise_construct,
+ std::uses_allocator_construction_args<_Tp1>(__a,
+ std::move(__pr).first),
+ std::uses_allocator_construction_args<_Tp2>(__a,
+ std::move(__pr).second));
+ }
+
+ template<typename _Tp, typename _Alloc, typename... _Args>
+ inline _Tp
+ make_obj_using_allocator(const _Alloc& __a, _Args&&... __args)
+ {
+ return std::make_from_tuple<_Tp>(uses_allocator_construction_args<_Tp>(
+ __a, std::forward<_Args>(__args)...));
+ }
+
+ template<typename _Tp, typename _Alloc, typename... _Args>
+ inline _Tp*
+ uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a,
+ _Args&&... __args)
+ {
+ void* __vp = const_cast<void*>(static_cast<const volatile void*>(__p));
+ return ::new(__vp) _Tp(std::make_obj_using_allocator<_Tp>(__a,
+ std::forward<_Args>(__args)...));
+ }
+
+#endif // C++2a
+
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
#endif // C++11
--- /dev/null
+// 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-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <testsuite_hooks.h>
+#include <testsuite_allocator.h>
+
+using test_allocator = __gnu_test::uneq_allocator<int>;
+
+struct Arg { };
+
+struct A
+{
+ A() : nargs(0) { }
+ A(float&) : nargs(1) { }
+ A(int, void*) : nargs(2) { }
+
+ // These should not be used:
+ A(const test_allocator& a);
+ A(float&, const test_allocator& a);
+ A(int, void*, const test_allocator& a);
+
+ const int nargs;
+ const int alloc_id = -1;
+
+ // std::uses_allocator<A, test_allocator> should be false:
+ using allocator_type = void*();
+};
+
+struct B
+{
+ // This means std::uses_allocator<B, test_allocator> is true:
+ using allocator_type = test_allocator;
+
+ B() : nargs(0) { }
+ B(float&) : nargs(1) { }
+ B(int, void*) : nargs(2) { }
+
+ B(std::allocator_arg_t, const test_allocator& a)
+ : nargs(0), alloc_id(a.get_personality()) { }
+ B(std::allocator_arg_t, const test_allocator& a, float&)
+ : nargs(1), alloc_id(a.get_personality()) { }
+ B(std::allocator_arg_t, const test_allocator& a, int, void*)
+ : nargs(2), alloc_id(a.get_personality()) { }
+ B(std::allocator_arg_t, const test_allocator& a, B&& b)
+ : nargs(b.nargs), alloc_id(a.get_personality()) { }
+
+ // These should not be used:
+ B(const test_allocator&);
+ B(float&, const test_allocator&, float&);
+ B(int, void*, const test_allocator&);
+ B(const test_allocator&, float&);
+ B(const test_allocator&, int, void*);
+ B(B&&);
+ B(B&&, const test_allocator&);
+
+ const int nargs;
+ const int alloc_id = -1;
+};
+
+struct C
+{
+ C() : nargs(0) { }
+ C(float&) : nargs(1) { }
+ C(int, void*) : nargs(2) { }
+
+ C(const test_allocator& a)
+ : nargs(0), alloc_id(a.get_personality()) { }
+ C(float&, const test_allocator& a)
+ : nargs(1), alloc_id(a.get_personality()) { }
+ C(int, void*, const test_allocator& a)
+ : nargs(2), alloc_id(a.get_personality()) { }
+ C(C&& c, const test_allocator& a)
+ : nargs(c.nargs), alloc_id(a.get_personality()) { }
+
+ C(C&&);
+
+ const int nargs;
+ const int alloc_id = -1;
+};
+
+namespace std {
+ // This means std::uses_allocator<C, test_allocator> is true:
+ template<> struct uses_allocator<C, test_allocator> : std::true_type { };
+}
+
+test_allocator alloc1(1);
+test_allocator alloc2(2);
+
+void
+test01()
+{
+ auto i0 = std::make_obj_using_allocator<int>(alloc1, 2);
+ VERIFY( i0 == 2 );
+
+ float f = 0.0f;
+
+ auto a0 = std::make_obj_using_allocator<A>(alloc1);
+ VERIFY( a0.nargs == 0 );
+ VERIFY( a0.alloc_id == -1 );
+ auto a1 = std::make_obj_using_allocator<A>(alloc1, f);
+ VERIFY( a1.nargs == 1 );
+ VERIFY( a1.alloc_id == -1 );
+ auto a2 = std::make_obj_using_allocator<A>(alloc1, 123, nullptr);
+ VERIFY( a2.nargs == 2 );
+ VERIFY( a2.alloc_id == -1 );
+
+ auto b0 = std::make_obj_using_allocator<B>(alloc1);
+ VERIFY( b0.nargs == 0 );
+ VERIFY( b0.alloc_id == 1 );
+ auto b1 = std::make_obj_using_allocator<B>(alloc2, f);
+ VERIFY( b1.nargs == 1 );
+ VERIFY( b1.alloc_id == 2 );
+ auto b2 = std::make_obj_using_allocator<B>(alloc1, 123, nullptr);
+ VERIFY( b2.nargs == 2 );
+ VERIFY( b2.alloc_id == 1 );
+
+ auto c0 = std::make_obj_using_allocator<C>(alloc1);
+ VERIFY( c0.nargs == 0 );
+ VERIFY( c0.alloc_id == 1 );
+ auto c1 = std::make_obj_using_allocator<C>(alloc2, f);
+ VERIFY( c1.nargs == 1 );
+ VERIFY( c1.alloc_id == 2 );
+ auto c2 = std::make_obj_using_allocator<C>(alloc1, 123, nullptr);
+ VERIFY( c2.nargs == 2 );
+ VERIFY( c2.alloc_id == 1 );
+}
+
+void
+test02()
+{
+ decltype(auto) b
+ = std::make_obj_using_allocator<const B>(alloc1, 123, nullptr);
+ static_assert( std::is_const_v<decltype(b)> );
+ VERIFY( b.nargs == 2 );
+ VERIFY( b.alloc_id == 1 );
+
+ decltype(auto) c = std::make_obj_using_allocator<const C>(alloc1);
+ static_assert( std::is_const_v<decltype(c)> );
+ VERIFY( c.nargs == 0 );
+ VERIFY( c.alloc_id == 1 );
+}
+
+void
+test03()
+{
+ B b;
+ decltype(auto) ref = std::make_obj_using_allocator<B&>(alloc1, b);
+ static_assert( std::is_same_v<decltype(ref), B&> );
+ VERIFY( &ref == &b );
+ VERIFY( ref.nargs == 0 );
+ VERIFY( ref.alloc_id == -1 );
+ const B& cref = std::make_obj_using_allocator<const B&>(alloc1, b);
+ static_assert( std::is_same_v<decltype(cref), const B&> );
+ VERIFY( &cref == &b );
+ VERIFY( cref.nargs == 0 );
+ VERIFY( cref.alloc_id == -1 );
+}
+
+void
+test04()
+{
+ struct D
+ {
+ D(std::allocator_arg_t) { }
+ D(std::allocator_arg_t, int) { }
+
+ // These should not be used:
+ D(std::allocator_arg_t, const test_allocator&);
+ D(std::allocator_arg_t, const test_allocator&, int);
+
+ ~D() { }
+ };
+
+ D d1 = std::make_obj_using_allocator<D>(alloc1, std::allocator_arg);
+
+ struct E
+ {
+ using allocator_type = test_allocator;
+
+ E(std::allocator_arg_t, const test_allocator&) { }
+ E(std::allocator_arg_t, int, const test_allocator&) { }
+
+ // These should not be used:
+ E(std::allocator_arg_t);
+ E(std::allocator_arg_t, int);
+
+ ~E() { }
+ };
+
+ E e1 = std::make_obj_using_allocator<E>(alloc1, std::allocator_arg);
+ E e2 = std::make_obj_using_allocator<E>(alloc2, std::allocator_arg, 2);
+}
+
+void
+test05()
+{
+ using std::pair;
+ std::piecewise_construct_t p;
+ std::tuple<> t0;
+ float f = 0.0f;
+ std::tuple<float&> t1(f);
+ std::tuple<int, void*> t2{};
+
+ auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t0, t0);
+ VERIFY( aa00.first.nargs == 0 );
+ VERIFY( aa00.first.alloc_id == -1 );
+ VERIFY( aa00.second.nargs == 0 );
+ VERIFY( aa00.second.alloc_id == -1 );
+ auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t0, t0);
+ VERIFY( ab00.first.nargs == 0 );
+ VERIFY( ab00.first.alloc_id == -1 );
+ VERIFY( ab00.second.nargs == 0 );
+ VERIFY( ab00.second.alloc_id == 1 );
+ auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t0, t0);
+ VERIFY( bc00.first.nargs == 0 );
+ VERIFY( bc00.first.alloc_id == 2 );
+ VERIFY( bc00.second.nargs == 0 );
+ VERIFY( bc00.second.alloc_id == 2 );
+ auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t0, t0);
+ VERIFY( cb00.first.nargs == 0 );
+ VERIFY( cb00.first.alloc_id == 2 );
+ VERIFY( cb00.second.nargs == 0 );
+ VERIFY( cb00.second.alloc_id == 2 );
+ auto cc00
+ = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t0, t0);
+ VERIFY( cc00.first.nargs == 0 );
+ VERIFY( cc00.first.alloc_id == 1 );
+ VERIFY( cc00.second.nargs == 0 );
+ VERIFY( cc00.second.alloc_id == 1 );
+
+ auto aa21 = std::make_obj_using_allocator<pair<A, A>>(alloc1, p, t2, t1);
+ VERIFY( aa21.first.nargs == 2 );
+ VERIFY( aa21.first.alloc_id == -1 );
+ VERIFY( aa21.second.nargs == 1 );
+ VERIFY( aa21.second.alloc_id == -1 );
+ auto ab21 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p, t2, t1);
+ VERIFY( ab21.first.nargs == 2 );
+ VERIFY( ab21.first.alloc_id == -1 );
+ VERIFY( ab21.second.nargs == 1 );
+ VERIFY( ab21.second.alloc_id == 1 );
+ auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, p, t1, t1);
+ VERIFY( bc11.first.nargs == 1 );
+ VERIFY( bc11.first.alloc_id == 2 );
+ VERIFY( bc11.second.nargs == 1 );
+ VERIFY( bc11.second.alloc_id == 2 );
+ auto cb12 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p, t1, t2);
+ VERIFY( cb12.first.nargs == 1 );
+ VERIFY( cb12.first.alloc_id == 2 );
+ VERIFY( cb12.second.nargs == 2 );
+ VERIFY( cb12.second.alloc_id == 2 );
+ auto cc22
+ = std::make_obj_using_allocator<pair<C, const C>>(alloc1, p, t2, t1);
+ VERIFY( cc22.first.nargs == 2 );
+ VERIFY( cc22.first.alloc_id == 1 );
+ VERIFY( cc22.second.nargs == 1 );
+ VERIFY( cc22.second.alloc_id == 1 );
+}
+
+void
+test06()
+{
+ using std::pair;
+ float f = 0.0f;
+
+ auto aa00 = std::make_obj_using_allocator<pair<A, A>>(alloc1);
+ VERIFY( aa00.first.nargs == 0 );
+ VERIFY( aa00.first.alloc_id == -1 );
+ VERIFY( aa00.second.nargs == 0 );
+ VERIFY( aa00.second.alloc_id == -1 );
+ auto ab00 = std::make_obj_using_allocator<pair<A, B>>(alloc1);
+ VERIFY( ab00.first.nargs == 0 );
+ VERIFY( ab00.first.alloc_id == -1 );
+ VERIFY( ab00.second.nargs == 0 );
+ VERIFY( ab00.second.alloc_id == 1 );
+ auto bc00 = std::make_obj_using_allocator<pair<B, C>>(alloc2);
+ VERIFY( bc00.first.nargs == 0 );
+ VERIFY( bc00.first.alloc_id == 2 );
+ VERIFY( bc00.second.nargs == 0 );
+ VERIFY( bc00.second.alloc_id == 2 );
+ auto cb00 = std::make_obj_using_allocator<pair<C, B>>(alloc2);
+ VERIFY( cb00.first.nargs == 0 );
+ VERIFY( cb00.first.alloc_id == 2 );
+ VERIFY( cb00.second.nargs == 0 );
+ VERIFY( cb00.second.alloc_id == 2 );
+ auto cc00 = std::make_obj_using_allocator<pair<C, const C>>(alloc1);
+ VERIFY( cc00.first.nargs == 0 );
+ VERIFY( cc00.first.alloc_id == 1 );
+ VERIFY( cc00.second.nargs == 0 );
+ VERIFY( cc00.second.alloc_id == 1 );
+
+ auto aa11 = std::make_obj_using_allocator<pair<A, A>>(alloc1, f, f);
+ VERIFY( aa11.first.nargs == 1 );
+ VERIFY( aa11.first.alloc_id == -1 );
+ VERIFY( aa11.second.nargs == 1 );
+ VERIFY( aa11.second.alloc_id == -1 );
+ auto aba1 = std::make_obj_using_allocator<pair<A, B>>(alloc1, A{}, f);
+ VERIFY( aba1.first.nargs == 0 );
+ VERIFY( aba1.first.alloc_id == -1 );
+ VERIFY( aba1.second.nargs == 1 );
+ VERIFY( aba1.second.alloc_id == 1 );
+ auto bc11 = std::make_obj_using_allocator<pair<B, C>>(alloc2, f, f);
+ VERIFY( bc11.first.nargs == 1 );
+ VERIFY( bc11.first.alloc_id == 2 );
+ VERIFY( bc11.second.nargs == 1 );
+ VERIFY( bc11.second.alloc_id == 2 );
+ auto cb1b = std::make_obj_using_allocator<pair<C, B>>(alloc2, f, B{});
+ VERIFY( cb1b.first.nargs == 1 );
+ VERIFY( cb1b.first.alloc_id == 2 );
+ VERIFY( cb1b.second.nargs == 0 );
+ VERIFY( cb1b.second.alloc_id == 2 );
+ auto cccc
+ = std::make_obj_using_allocator<pair<C, const C>>(alloc1, C{}, C{});
+ VERIFY( cccc.first.nargs == 0 );
+ VERIFY( cccc.first.alloc_id == 1 );
+ VERIFY( cccc.second.nargs == 0 );
+ VERIFY( cccc.second.alloc_id == 1 );
+
+ pair<float&, A> p1a(f, A{});
+ pair<float&, float&> p11(f, f);
+ auto aa1a = std::make_obj_using_allocator<pair<A, A>>(alloc1, p1a);
+ VERIFY( aa1a.first.nargs == 1 );
+ VERIFY( aa1a.first.alloc_id == -1 );
+ VERIFY( aa1a.second.nargs == 0 );
+ VERIFY( aa1a.second.alloc_id == -1 );
+ auto ab11 = std::make_obj_using_allocator<pair<A, B>>(alloc1, p11);
+ VERIFY( ab11.first.nargs == 1 );
+ VERIFY( ab11.first.alloc_id == -1 );
+ VERIFY( ab11.second.nargs == 1 );
+ VERIFY( ab11.second.alloc_id == 1 );
+ auto cb11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, p11);
+ VERIFY( cb11.first.nargs == 1 );
+ VERIFY( cb11.first.alloc_id == 2 );
+ VERIFY( cb11.second.nargs == 1 );
+ VERIFY( cb11.second.alloc_id == 2 );
+
+ auto bcbc = std::make_obj_using_allocator<pair<B, C>>(alloc2, pair<B, C>());
+ VERIFY( bcbc.first.nargs == 0 );
+ VERIFY( bcbc.first.alloc_id == 2 );
+ VERIFY( bcbc.second.nargs == 0 );
+ VERIFY( bcbc.second.alloc_id == 2 );
+
+ auto cc11 = std::make_obj_using_allocator<pair<C, B>>(alloc2, std::move(p11));
+ VERIFY( cc11.first.nargs == 1 );
+ VERIFY( cc11.first.alloc_id == 2 );
+ VERIFY( cc11.second.nargs == 1 );
+ VERIFY( cc11.second.alloc_id == 2 );
+}
+
+void
+test07()
+{
+ using nested_pair = std::pair<const std::pair<B, const B>, C>;
+ auto p = std::make_obj_using_allocator<const nested_pair>(alloc1);
+ VERIFY( p.first.first.alloc_id == 1 );
+ VERIFY( p.first.second.alloc_id == 1 );
+ VERIFY( p.second.alloc_id == 1 );
+}
+
+void
+test08()
+{
+ // LWG DR 3187.
+ // P0591R4 reverted DR 2586 fixes to scoped_allocator_adaptor::construct()
+
+ struct X {
+ using allocator_type = std::allocator<X>;
+ X(std::allocator_arg_t, allocator_type&&) { }
+ X(const allocator_type&) { }
+ };
+
+ std::allocator<X> a;
+ std::make_obj_using_allocator<X>(a);
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+ test05();
+ test06();
+ test07();
+ test08();
+}