EricWF updated this revision to Diff 80873. EricWF added a comment. Fix copy paste errors in tests.
https://reviews.llvm.org/D27612 Files: include/scoped_allocator test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp
Index: test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_values.pass.cpp @@ -0,0 +1,147 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2, class Tp, class Vp> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, Tp&&, Up&&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::move(x), y); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, x, std::move(y)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int &&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&>&&, + std::tuple<int &&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::move(x), std::move(y)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&&>&&, + std::tuple<int const&&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} Index: test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_rvalue.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, pair<T1, T2>&&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, std::move(y)); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&>&&, + std::tuple<int const&&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const &>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + PairIn in(x, y); + A.construct(ptr, std::move(in)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&&>&&, + std::tuple<int const&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} Index: test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_piecewise.pass.cpp @@ -0,0 +1,156 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2, class ...Args1, class ...Args2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, +// piecewise_construct_t, tuple<Args1...>, tuple<Args2...>) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&>&&, + std::tuple<int const&&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(y)); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(x), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int &&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&>&&, + std::tuple<int &&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + int x = 42; + const int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr, std::piecewise_construct, + std::forward_as_tuple(std::move(x)), + std::forward_as_tuple(std::move(y))); + assert(checkConstruct<int&&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&&>&&, + std::tuple<int const&&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} Index: test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair_const_lvalue_pair.pass.cpp @@ -0,0 +1,155 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*, pair<T1, T2>const&) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 1>; + using U = UsesAllocatorV2<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int&>&&, + std::tuple<int const&, SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 1>; + using U = NotUsesAllocator<VoidAlloc, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const&>; + int x = 42; + const int y = 101; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct<int const&>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&, int const&>&&, + std::tuple<int const&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 1>; + using U = UsesAllocatorV2<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int&, int const&&>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, std::move(y)); + A.construct(ptr, in); + assert(checkConstruct<int&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int&>&&, + std::tuple<int const&, SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 1>; + using U = NotUsesAllocator<VoidAlloc2, 1>; + using Pair = std::pair<T, U>; + using PairIn = std::pair<int, int const &>; + int x = 42; + int y = 101; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + const PairIn in(x, y); + A.construct(ptr, in); + assert(checkConstruct<int const&>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<int const&>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&, int const&>&&, + std::tuple<int const&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} Index: test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp =================================================================== --- /dev/null +++ test/std/utilities/allocator.adaptor/allocator.adaptor.members/construct_pair.pass.cpp @@ -0,0 +1,139 @@ +//===----------------------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// UNSUPPORTED: c++98, c++03 + +// <scoped_allocator> + +// template <class OtherAlloc, class ...InnerAlloc> +// class scoped_allocator_adaptor + +// template <class U1, class U2> +// void scoped_allocator_adaptor::construct(pair<U1, U2>*) + +#include <scoped_allocator> +#include <type_traits> +#include <utility> +#include <tuple> +#include <cassert> +#include <cstdlib> +#include "uses_alloc_types.hpp" +#include "controlled_allocators.hpp" + + +void test_no_inner_alloc() +{ + using VoidAlloc = CountingAllocator<void>; + AllocController P; + { + using T = UsesAllocatorV1<VoidAlloc, 0>; + using U = UsesAllocatorV2<VoidAlloc, 0>; + using Pair = std::pair<T, U>; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_AllocLast, CA)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&>&&, + std::tuple<SA&>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + + } + P.reset(); + { + using T = UsesAllocatorV3<VoidAlloc, 0>; + using U = NotUsesAllocator<VoidAlloc, 0>; + using Pair = std::pair<T, U>; + using Alloc = CountingAllocator<Pair>; + using SA = std::scoped_allocator_adaptor<Alloc>; + static_assert(std::uses_allocator<T, CountingAllocator<T> >::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Alloc CA(P); + SA A(CA); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, CA)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((P.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SA&>&&, + std::tuple<>&& + >(CA, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} + +void test_with_inner_alloc() +{ + using VoidAlloc1 = CountingAllocator<void, 1>; + using VoidAlloc2 = CountingAllocator<void, 2>; + + AllocController POuter; + AllocController PInner; + { + using T = UsesAllocatorV1<VoidAlloc2, 0>; + using U = UsesAllocatorV2<VoidAlloc2, 0>; + using Pair = std::pair<T, U>; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_AllocLast)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&>&&, + std::tuple<SAInner&>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } + PInner.reset(); + POuter.reset(); + { + using T = UsesAllocatorV3<VoidAlloc2, 0>; + using U = NotUsesAllocator<VoidAlloc2, 0>; + using Pair = std::pair<T, U>; + using Outer = CountingAllocator<Pair, 1>; + using Inner = CountingAllocator<Pair, 2>; + using SA = std::scoped_allocator_adaptor<Outer, Inner>; + using SAInner = std::scoped_allocator_adaptor<Inner>; + static_assert(!std::uses_allocator<T, Outer>::value, ""); + static_assert(std::uses_allocator<T, Inner>::value, ""); + Pair * ptr = (Pair*)std::malloc(sizeof(Pair)); + Outer O(POuter); + Inner I(PInner); + SA A(O, I); + A.construct(ptr); + assert(checkConstruct<>(ptr->first, UA_AllocArg, I)); + assert(checkConstruct<>(ptr->second, UA_None)); + assert((POuter.checkConstruct<std::piecewise_construct_t const&, + std::tuple<std::allocator_arg_t const&, SAInner&>&&, + std::tuple<>&& + >(O, ptr))); + A.destroy(ptr); + std::free(ptr); + } +} +int main() { + test_no_inner_alloc(); + test_with_inner_alloc(); +} Index: include/scoped_allocator =================================================================== --- include/scoped_allocator +++ include/scoped_allocator @@ -500,6 +500,56 @@ void construct(_Tp* __p, _Args&& ...__args) {__construct(__uses_alloc_ctor<_Tp, inner_allocator_type, _Args...>(), __p, _VSTD::forward<_Args>(__args)...);} + + template <class _T1, class _T2, class... _Args1, class... _Args2> + void construct(pair<_T1, _T2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + typedef __outermost<outer_allocator_type> _OM; + allocator_traits<typename _OM::type>::construct( + _OM()(outer_allocator()), __p, piecewise_construct + , __transform_tuple( + typename __uses_alloc_ctor< + _T1, inner_allocator_type, _Args1... + >::type() + , _VSTD::move(__x) + , typename __make_tuple_indices<sizeof...(_Args1)>::type{} + ) + , __transform_tuple( + typename __uses_alloc_ctor< + _T2, inner_allocator_type, _Args2... + >::type() + , _VSTD::move(__y) + , typename __make_tuple_indices<sizeof...(_Args2)>::type{} + ) + ); + } + + template <class _T1, class _T2> + void construct(pair<_T1, _T2>* __p) + { construct(__p, piecewise_construct, tuple<>{}, tuple<>{}); } + + template <class _T1, class _T2, class _Up, class _Vp> + void construct(pair<_T1, _T2>* __p, _Up&& __x, _Vp&& __y) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x)), + _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__y))); + } + + template <class _T1, class _T2, class _Up, class _Vp> + void construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(__x.first), + _VSTD::forward_as_tuple(__x.second)); + } + + template <class _T1, class _T2, class _Up, class _Vp> + void construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) { + construct(__p, piecewise_construct, + _VSTD::forward_as_tuple(_VSTD::forward<_Up>(__x.first)), + _VSTD::forward_as_tuple(_VSTD::forward<_Vp>(__x.second))); + } + template <class _Tp> _LIBCPP_INLINE_VISIBILITY void destroy(_Tp* __p) @@ -515,6 +565,7 @@ private: + template <class _OuterA2, class = typename enable_if< is_constructible<outer_allocator_type, _OuterA2>::value @@ -566,6 +617,36 @@ ); } + template <class ..._Args, size_t ..._Idx> + _LIBCPP_INLINE_VISIBILITY + tuple<_Args&&...> + __transform_tuple(integral_constant<int, 0>, tuple<_Args...>&& __t, + __tuple_indices<_Idx...>) + { + return _VSTD::forward_as_tuple(_VSTD::get<_Idx>(_VSTD::move(__t))...); + } + + template <class ..._Args, size_t ..._Idx> + _LIBCPP_INLINE_VISIBILITY + tuple<allocator_arg_t const&, inner_allocator_type&, _Args&&...> + __transform_tuple(integral_constant<int, 1>, tuple<_Args...> && __t, + __tuple_indices<_Idx...>) + { + using _Tup = tuple<allocator_arg_t const&, inner_allocator_type&, _Args&&...>; + return _Tup(allocator_arg, inner_allocator(), + _VSTD::get<_Idx>(_VSTD::move(__t))...); + } + + template <class ..._Args, size_t ..._Idx> + _LIBCPP_INLINE_VISIBILITY + tuple<_Args&&..., inner_allocator_type&> + __transform_tuple(integral_constant<int, 2>, tuple<_Args...> && __t, + __tuple_indices<_Idx...>) + { + using _Tup = tuple<_Args&&..., inner_allocator_type&>; + return _Tup(_VSTD::get<_Idx>(_VSTD::move(__t))..., inner_allocator()); + } + template <class...> friend class __scoped_allocator_storage; };
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits