xref: /llvm-project/libcxx/test/libcxx/ranges/range.nonprop.cache/emplace.pass.cpp (revision b8cb1dc9ea87faa8e8e9ab7a31710a8c0bb8b084)
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 // UNSUPPORTED: c++03, c++11, c++14, c++17
10 
11 // template<class ...Args>
12 // constexpr T& __emplace(Args&& ...);
13 
14 #include <ranges>
15 
16 #include <cassert>
17 #include <tuple>
18 
19 template<int I>
20 struct X {
21   int value = -1;
22   template<int J>
operator ==(X const & a,X<J> const & b)23   friend constexpr bool operator==(X const& a, X<J> const& b) { return I == J && a.value == b.value; }
24 };
25 
26 struct NonMovable {
27   int value = -1;
28   NonMovable() = default;
NonMovableNonMovable29   constexpr explicit NonMovable(int v) : value(v) { }
30   NonMovable(NonMovable&&) = delete;
31   NonMovable& operator=(NonMovable&&) = delete;
32 };
33 
test()34 constexpr bool test() {
35   {
36     using T = std::tuple<>;
37     using Cache = std::ranges::__non_propagating_cache<T>;
38     Cache cache;
39     T& result = cache.__emplace();
40     assert(&result == &*cache);
41     assert(result == T());
42   }
43 
44   {
45     using T = std::tuple<X<0>>;
46     using Cache = std::ranges::__non_propagating_cache<T>;
47     Cache cache;
48     T& result = cache.__emplace();
49     assert(&result == &*cache);
50     assert(result == T());
51   }
52   {
53     using T = std::tuple<X<0>>;
54     using Cache = std::ranges::__non_propagating_cache<T>;
55     Cache cache;
56     T& result = cache.__emplace(X<0>{0});
57     assert(&result == &*cache);
58     assert(result == T(X<0>{0}));
59   }
60 
61   {
62     using T = std::tuple<X<0>, X<1>>;
63     using Cache = std::ranges::__non_propagating_cache<T>;
64     Cache cache;
65     T& result = cache.__emplace();
66     assert(&result == &*cache);
67     assert(result == T());
68   }
69   {
70     using T = std::tuple<X<0>, X<1>>;
71     using Cache = std::ranges::__non_propagating_cache<T>;
72     Cache cache;
73     T& result = cache.__emplace(X<0>{0}, X<1>{1});
74     assert(&result == &*cache);
75     assert(result == T(X<0>{0}, X<1>{1}));
76   }
77 
78   // Make sure that we do not require the type to be movable when we emplace it.
79   // Move elision should be performed instead, see http://eel.is/c++draft/range.nonprop.cache#note-1.
80   {
81     using Cache = std::ranges::__non_propagating_cache<NonMovable>;
82     Cache cache;
83     NonMovable& result = cache.__emplace();
84     assert(&result == &*cache);
85     assert(result.value == -1);
86   }
87 
88   return true;
89 }
90 
main(int,char **)91 int main(int, char**) {
92   static_assert(test());
93   test();
94   return 0;
95 }
96