1 | #include <c10/util/C++17.h> |
2 | #include <gtest/gtest.h> |
3 | |
4 | namespace { |
5 | |
6 | namespace test_min { |
7 | using c10::guts::min; |
8 | static_assert(min(3, 5) == 3, "" ); |
9 | static_assert(min(5, 3) == 3, "" ); |
10 | static_assert(min(3, 3) == 3, "" ); |
11 | static_assert(min(3.0, 3.1) == 3.0, "" ); |
12 | } // namespace test_min |
13 | |
14 | namespace test_max { |
15 | using c10::guts::max; |
16 | static_assert(max(3, 5) == 5, "" ); |
17 | static_assert(max(5, 3) == 5, "" ); |
18 | static_assert(max(3, 3) == 3, "" ); |
19 | static_assert(max(3.0, 3.1) == 3.1, "" ); |
20 | } // namespace test_max |
21 | |
22 | namespace test_if_constexpr { |
23 | |
24 | using c10::guts::if_constexpr; |
25 | |
26 | TEST(if_constexpr, whenIsTrue_thenReturnsTrueCase) { |
27 | EXPECT_EQ( |
28 | 4, if_constexpr<true>([](auto) { return 4; }, [](auto) { return 5; })); |
29 | } |
30 | |
31 | TEST(if_constexpr, whenIsFalse_thenReturnsFalseCase) { |
32 | EXPECT_EQ( |
33 | 5, if_constexpr<false>([](auto) { return 4; }, [](auto) { return 5; })); |
34 | } |
35 | |
36 | struct MovableOnly final { |
37 | int value; |
38 | |
39 | MovableOnly(int v) : value(v) {} |
40 | MovableOnly(MovableOnly&&) = default; |
41 | MovableOnly(const MovableOnly&) = delete; |
42 | MovableOnly& operator=(MovableOnly&&) = default; |
43 | MovableOnly& operator=(const MovableOnly&) = delete; |
44 | }; |
45 | |
46 | TEST(if_constexpr, worksWithMovableOnlyTypes_withIdentityArg) { |
47 | EXPECT_EQ( |
48 | 4, |
49 | if_constexpr<true>( |
50 | [](auto) { return MovableOnly(4); }, |
51 | [](auto) { return MovableOnly(5); }) |
52 | .value); |
53 | EXPECT_EQ( |
54 | 5, |
55 | if_constexpr<false>( |
56 | [](auto) { return MovableOnly(4); }, |
57 | [](auto) { return MovableOnly(5); }) |
58 | .value); |
59 | } |
60 | |
61 | TEST(if_constexpr, worksWithMovableOnlyTypes_withoutIdentityArg) { |
62 | EXPECT_EQ( |
63 | 4, |
64 | if_constexpr<true>( |
65 | [] { return MovableOnly(4); }, [] { return MovableOnly(5); }) |
66 | .value); |
67 | EXPECT_EQ( |
68 | 5, |
69 | if_constexpr<false>( |
70 | [] { return MovableOnly(4); }, [] { return MovableOnly(5); }) |
71 | .value); |
72 | } |
73 | |
74 | struct MyClass1 { |
75 | int value; |
76 | }; |
77 | |
78 | struct MyClass2 { |
79 | int val; |
80 | }; |
81 | |
82 | template <class T> |
83 | int func(T t) { |
84 | return if_constexpr<std::is_same<T, MyClass1>::value>( |
85 | [&](auto _) { |
86 | return _(t).value; |
87 | }, // this code is invalid for T == MyClass2 |
88 | [&](auto _) { return _(t).val; } // this code is invalid for T == MyClass1 |
89 | ); |
90 | } |
91 | |
92 | TEST(if_constexpr, otherCaseCanHaveInvalidCode) { |
93 | EXPECT_EQ(8, func(MyClass1{/* .value = */ 8})); |
94 | EXPECT_EQ(4, func(MyClass2{/* .val = */ 4})); |
95 | } |
96 | |
97 | TEST(if_constexpr, worksWithoutElseCase_withIdentityArg) { |
98 | int var = 5; |
99 | if_constexpr<false>([&](auto) { var = 3; }); |
100 | EXPECT_EQ(5, var); |
101 | if_constexpr<true>([&](auto) { var = 3; }); |
102 | EXPECT_EQ(3, var); |
103 | } |
104 | |
105 | TEST(if_constexpr, worksWithoutElseCase_withoutIdentityArg) { |
106 | int var = 5; |
107 | if_constexpr<false>([&] { var = 3; }); |
108 | EXPECT_EQ(5, var); |
109 | if_constexpr<true>([&] { var = 3; }); |
110 | EXPECT_EQ(3, var); |
111 | } |
112 | |
113 | TEST(if_constexpr, returnTypeCanDiffer_withIdentityArg) { |
114 | auto a_string = if_constexpr<false>( |
115 | [&](auto) -> int64_t { return 3; }, |
116 | [&](auto) -> std::string { return "3" ; }); |
117 | static_assert(std::is_same<std::string, decltype(a_string)>::value, "" ); |
118 | |
119 | // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) |
120 | auto an_int = if_constexpr<true>( |
121 | [&](auto) -> int64_t { return 3; }, |
122 | [&](auto) -> std::string { return "3" ; }); |
123 | static_assert(std::is_same<int64_t, decltype(an_int)>::value, "" ); |
124 | } |
125 | |
126 | TEST(if_constexpr, returnTypeCanDiffer_withoutIdentityArg) { |
127 | auto a_string = if_constexpr<false>( |
128 | [&]() -> int64_t { return 3; }, [&]() -> std::string { return "3" ; }); |
129 | static_assert(std::is_same<std::string, decltype(a_string)>::value, "" ); |
130 | |
131 | // NOLINTNEXTLINE(clang-analyzer-deadcode.DeadStores) |
132 | auto an_int = if_constexpr<true>( |
133 | [&]() -> int64_t { return 3; }, [&]() -> std::string { return "3" ; }); |
134 | static_assert(std::is_same<int64_t, decltype(an_int)>::value, "" ); |
135 | } |
136 | |
137 | } // namespace test_if_constexpr |
138 | } // namespace |
139 | |