1//===----------------------------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is dual licensed under the MIT and the University of Illinois Open
6// Source Licenses. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10// UNSUPPORTED: c++98, c++03
11
12// <tuple>
13
14// template <class... Types> class tuple;
15
16// template <class Alloc>
17//   tuple(allocator_arg_t, const Alloc& a);
18
19// NOTE: this constructor does not currently support tags derived from
20// allocator_arg_t because libc++ has to deduce the parameter as a template
21// argument. See PR27684 (https://bugs.llvm.org/show_bug.cgi?id=27684)
22
23#include <tuple>
24#include <cassert>
25
26#include "DefaultOnly.h"
27#include "allocators.h"
28#include "../alloc_first.h"
29#include "../alloc_last.h"
30
31template <class T = void>
32struct NonDefaultConstructible {
33  constexpr NonDefaultConstructible() {
34      static_assert(!std::is_same<T, T>::value, "Default Ctor instantiated");
35  }
36
37  explicit constexpr NonDefaultConstructible(int) {}
38};
39
40
41struct DerivedFromAllocArgT : std::allocator_arg_t {};
42
43int main()
44{
45    {
46        std::tuple<> t(std::allocator_arg, A1<int>());
47    }
48    {
49        std::tuple<int> t(std::allocator_arg, A1<int>());
50        assert(std::get<0>(t) == 0);
51    }
52    {
53        std::tuple<DefaultOnly> t(std::allocator_arg, A1<int>());
54        assert(std::get<0>(t) == DefaultOnly());
55    }
56    {
57        assert(!alloc_first::allocator_constructed);
58        std::tuple<alloc_first> t(std::allocator_arg, A1<int>(5));
59        assert(alloc_first::allocator_constructed);
60        assert(std::get<0>(t) == alloc_first());
61    }
62    {
63        assert(!alloc_last::allocator_constructed);
64        std::tuple<alloc_last> t(std::allocator_arg, A1<int>(5));
65        assert(alloc_last::allocator_constructed);
66        assert(std::get<0>(t) == alloc_last());
67    }
68    {
69        alloc_first::allocator_constructed = false;
70        std::tuple<DefaultOnly, alloc_first> t(std::allocator_arg, A1<int>(5));
71        assert(std::get<0>(t) == DefaultOnly());
72        assert(alloc_first::allocator_constructed);
73        assert(std::get<1>(t) == alloc_first());
74    }
75    {
76        alloc_first::allocator_constructed = false;
77        alloc_last::allocator_constructed = false;
78        std::tuple<DefaultOnly, alloc_first, alloc_last> t(std::allocator_arg,
79                                                           A1<int>(5));
80        assert(std::get<0>(t) == DefaultOnly());
81        assert(alloc_first::allocator_constructed);
82        assert(std::get<1>(t) == alloc_first());
83        assert(alloc_last::allocator_constructed);
84        assert(std::get<2>(t) == alloc_last());
85    }
86    {
87        alloc_first::allocator_constructed = false;
88        alloc_last::allocator_constructed = false;
89        std::tuple<DefaultOnly, alloc_first, alloc_last> t(std::allocator_arg,
90                                                           A2<int>(5));
91        assert(std::get<0>(t) == DefaultOnly());
92        assert(!alloc_first::allocator_constructed);
93        assert(std::get<1>(t) == alloc_first());
94        assert(!alloc_last::allocator_constructed);
95        assert(std::get<2>(t) == alloc_last());
96    }
97    {
98        // Test that the uses-allocator default constructor does not evaluate
99        // its SFINAE when it otherwise shouldn't be selected. Do this by
100        // using 'NonDefaultConstructible' which will cause a compile error
101        // if std::is_default_constructible is evaluated on it.
102        using T = NonDefaultConstructible<>;
103        T v(42);
104        std::tuple<T, T> t(v, v);
105        (void)t;
106        std::tuple<T, T> t2(42, 42);
107        (void)t2;
108    }
109}
110