1//===----------------------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9// <tuple>
10
11// template <class... Types>
12// template <class Alloc, class U1, class U2>
13// constexpr explicit(see below)
14// tuple<Types...>::tuple(allocator_arg_t, const Alloc& a, const pair<U1,
15// U2>&& u);
16
17// Constraints:
18// - sizeof...(Types) is 2 and
19// - is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
20// - is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
21
22// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
23
24#include <cassert>
25#include <tuple>
26#include <utility>
27
28#include "copy_move_types.h"
29#include "test_allocator.h"
30
31// test constraints
32// sizeof...(Types) == 2
33static_assert(std::is_constructible_v<std::tuple<ConstMove, int>, std::allocator_arg_t, test_allocator<int>,
34 const std::pair<ConstMove, int>&&>);
35
36static_assert(!std::is_constructible_v< std::tuple<ConstMove>, std::allocator_arg_t, test_allocator<int>,
37 const std::pair<ConstMove, int>&&>);
38
39static_assert(!std::is_constructible_v< std::tuple<ConstMove, int, int>, std::allocator_arg_t, test_allocator<int>,
40 const std::pair<ConstMove, int>&&>);
41
42// test constraints
43// is_constructible_v<T0, decltype(get<0>(FWD(u)))> is true and
44// is_constructible_v<T1, decltype(get<1>(FWD(u)))> is true.
45static_assert(std::is_constructible_v<std::tuple<int, int>, std::allocator_arg_t, test_allocator<int>,
46 const std::pair<int, int>&&>);
47
48static_assert(!std::is_constructible_v< std::tuple<NoConstructorFromInt, int>, std::allocator_arg_t,
49 test_allocator<int>, const std::pair<int, int>&&>);
50
51static_assert(!std::is_constructible_v< std::tuple<int, NoConstructorFromInt>, std::allocator_arg_t,
52 test_allocator<int>, const std::pair<int, int>&&>);
53
54static_assert(!std::is_constructible_v< std::tuple<NoConstructorFromInt, NoConstructorFromInt>, std::allocator_arg_t,
55 test_allocator<int>, const std::pair<int, int>&&>);
56
57// test: The expression inside explicit is equivalent to:
58// !is_convertible_v<decltype(get<0>(FWD(u))), T0> ||
59// !is_convertible_v<decltype(get<1>(FWD(u))), T1>
60static_assert(
61 ImplicitlyConstructible< std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>, std::allocator_arg_t,
62 test_allocator<int>, const std::pair<ConstMove, ConstMove>&&>);
63
64static_assert(
65 !ImplicitlyConstructible<std::tuple<ConvertibleFrom<ConstMove>, ExplicitConstructibleFrom<ConstMove>>,
66 std::allocator_arg_t, test_allocator<int>, const std::pair<ConstMove, ConstMove>&&>);
67
68static_assert(
69 !ImplicitlyConstructible<std::tuple<ExplicitConstructibleFrom<ConstMove>, ConvertibleFrom<ConstMove>>,
70 std::allocator_arg_t, test_allocator<int>, const std::pair<ConstMove, ConstMove>&&>);
71
72constexpr bool test() {
73 // test implicit conversions.
74 {
75 const std::pair<ConstMove, int> p{1, 2};
76 std::tuple<ConvertibleFrom<ConstMove>, ConvertibleFrom<int>> t = {std::allocator_arg, test_allocator<int>{},
77 std::move(p)};
78 assert(std::get<0>(t).v.val == 1);
79 assert(std::get<1>(t).v == 2);
80 assert(std::get<0>(t).alloc_constructed);
81 assert(std::get<1>(t).alloc_constructed);
82 }
83
84 // test explicit conversions.
85 {
86 const std::pair<ConstMove, int> p{1, 2};
87 std::tuple<ExplicitConstructibleFrom<ConstMove>, ExplicitConstructibleFrom<int>> t{
88 std::allocator_arg, test_allocator<int>{}, std::move(p)};
89 assert(std::get<0>(t).v.val == 1);
90 assert(std::get<1>(t).v == 2);
91 assert(std::get<0>(t).alloc_constructed);
92 assert(std::get<1>(t).alloc_constructed);
93 }
94
95 // non const overload should be called
96 {
97 const std::pair<TracedCopyMove, TracedCopyMove> p;
98 std::tuple<ConvertibleFrom<TracedCopyMove>, TracedCopyMove> t = {std::allocator_arg, test_allocator<int>{},
99 std::move(p)};
100 assert(constMoveCtrCalled(std::get<0>(t).v));
101 assert(constMoveCtrCalled(std::get<1>(t)));
102 assert(std::get<0>(t).alloc_constructed);
103 assert(std::get<1>(t).alloc_constructed);
104 }
105
106 return true;
107}
108
109int main(int, char**) {
110 test();
111 static_assert(test());
112
113 return 0;
114}
115

source code of libcxx/test/std/utilities/tuple/tuple.tuple/tuple.cnstr/alloc_const_move_pair.pass.cpp