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