xref: /llvm-project/libcxx/test/std/utilities/tuple/tuple.tuple/tuple.assign/laziness.pass.cpp (revision a0839b14df6de99fe29bee7cdfff182d50de665d)
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
10 
11 // This test ensures that std::tuple is lazy when it comes to checking whether
12 // the elements it is assigned from can be used to assign to the types in
13 // the tuple.
14 
15 #include <tuple>
16 #include <array>
17 
18 template <bool Enable, class ...Class>
BlowUp()19 constexpr typename std::enable_if<Enable, bool>::type BlowUp() {
20   static_assert(Enable && sizeof...(Class) != sizeof...(Class), "");
21   return true;
22 }
23 
24 template<class T>
25 struct Fail {
26   static_assert(sizeof(T) != sizeof(T), "");
27   using type = void;
28 };
29 
30 struct NoAssign {
31   NoAssign() = default;
32   NoAssign(NoAssign const&) = default;
33   template <class T, class = typename std::enable_if<sizeof(T) != sizeof(T)>::type>
operator =NoAssign34   NoAssign& operator=(T) { return *this; }
35 };
36 
37 template <int>
38 struct DieOnAssign {
39   DieOnAssign() = default;
40   template <class T, class X = typename std::enable_if<!std::is_same<T, DieOnAssign>::value>::type,
41                      class = typename Fail<X>::type>
operator =DieOnAssign42   DieOnAssign& operator=(T) {
43     return *this;
44   }
45 };
46 
test_arity_checks()47 void test_arity_checks() {
48   {
49     using T = std::tuple<int, DieOnAssign<0>, int>;
50     using P = std::pair<int, int>;
51     static_assert(!std::is_assignable<T&, P const&>::value, "");
52   }
53   {
54     using T = std::tuple<int, int, DieOnAssign<1> >;
55     using A = std::array<int, 1>;
56     static_assert(!std::is_assignable<T&, A const&>::value, "");
57   }
58 }
59 
test_assignability_checks()60 void test_assignability_checks() {
61   {
62     using T1 = std::tuple<int, NoAssign, DieOnAssign<2> >;
63     using T2 = std::tuple<long, long, long>;
64     static_assert(!std::is_assignable<T1&, T2 const&>::value, "");
65   }
66   {
67     using T1 = std::tuple<NoAssign, DieOnAssign<3> >;
68     using T2 = std::pair<long, double>;
69     static_assert(!std::is_assignable<T1&, T2 const&>::value, "");
70   }
71 }
72 
main(int,char **)73 int main(int, char**) {
74   test_arity_checks();
75   test_assignability_checks();
76   return 0;
77 }
78