overload_test.cc (6293B)
1 // Copyright 2023 The Abseil Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // https://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #include "absl/functional/overload.h" 16 17 #include <cstdint> 18 #include <string> 19 #include <type_traits> 20 21 #include "gtest/gtest.h" 22 #include "absl/base/config.h" 23 #include "absl/strings/str_cat.h" 24 #include "absl/strings/string_view.h" 25 #include "absl/types/variant.h" 26 27 namespace { 28 29 TEST(OverloadTest, DispatchConsidersTypeWithAutoFallback) { 30 auto overloaded = absl::Overload{ 31 [](int v) { return absl::StrCat("int ", v); }, 32 [](double v) { return absl::StrCat("double ", v); }, 33 [](const char* v) { return absl::StrCat("const char* ", v); }, 34 [](auto v) { return absl::StrCat("auto ", v); }, 35 }; 36 37 EXPECT_EQ("int 1", overloaded(1)); 38 EXPECT_EQ("double 2.5", overloaded(2.5)); 39 EXPECT_EQ("const char* hello", overloaded("hello")); 40 EXPECT_EQ("auto 1.5", overloaded(1.5f)); 41 } 42 43 TEST(OverloadTest, DispatchConsidersNumberOfArguments) { 44 auto overloaded = absl::Overload{ 45 [](int a) { return a + 1; }, 46 [](int a, int b) { return a * b; }, 47 []() -> absl::string_view { return "none"; }, 48 }; 49 50 EXPECT_EQ(3, overloaded(2)); 51 EXPECT_EQ(21, overloaded(3, 7)); 52 EXPECT_EQ("none", overloaded()); 53 } 54 55 TEST(OverloadTest, SupportsConstantEvaluation) { 56 auto overloaded = absl::Overload{ 57 [](int a) { return a + 1; }, 58 [](int a, int b) { return a * b; }, 59 []() -> absl::string_view { return "none"; }, 60 }; 61 62 static_assert(overloaded() == "none"); 63 static_assert(overloaded(2) == 3); 64 static_assert(overloaded(3, 7) == 21); 65 } 66 67 TEST(OverloadTest, PropogatesDefaults) { 68 auto overloaded = absl::Overload{ 69 [](int a, int b = 5) { return a * b; }, 70 [](double c) { return c; }, 71 }; 72 73 EXPECT_EQ(21, overloaded(3, 7)); 74 EXPECT_EQ(35, overloaded(7)); 75 EXPECT_EQ(2.5, overloaded(2.5)); 76 } 77 78 TEST(OverloadTest, AmbiguousWithDefaultsNotInvocable) { 79 auto overloaded = absl::Overload{ 80 [](int a, int b = 5) { return a * b; }, 81 [](int c) { return c; }, 82 }; 83 84 static_assert(!std::is_invocable_v<decltype(overloaded), int>); 85 static_assert(std::is_invocable_v<decltype(overloaded), int, int>); 86 } 87 88 TEST(OverloadTest, AmbiguousDuplicatesNotInvocable) { 89 auto overloaded = absl::Overload{ 90 [](int a) { return a; }, 91 [](int c) { return c; }, 92 }; 93 94 static_assert(!std::is_invocable_v<decltype(overloaded), int>); 95 } 96 97 TEST(OverloadTest, AmbiguousConversionNotInvocable) { 98 auto overloaded = absl::Overload{ 99 [](uint16_t a) { return a; }, 100 [](uint64_t c) { return c; }, 101 }; 102 103 static_assert(!std::is_invocable_v<decltype(overloaded), int>); 104 } 105 106 TEST(OverloadTest, AmbiguousConversionWithAutoNotInvocable) { 107 auto overloaded = absl::Overload{ 108 [](auto a) { return a; }, 109 [](auto c) { return c; }, 110 }; 111 112 static_assert(!std::is_invocable_v<decltype(overloaded), int>); 113 } 114 115 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L 116 117 TEST(OverloadTest, AmbiguousConversionWithAutoAndTemplateNotInvocable) { 118 auto overloaded = absl::Overload{ 119 [](auto a) { return a; }, 120 []<class T>(T c) { return c; }, 121 }; 122 123 static_assert(!std::is_invocable_v<decltype(overloaded), int>); 124 } 125 126 TEST(OverloadTest, DispatchConsidersTypeWithTemplateFallback) { 127 auto overloaded = absl::Overload{ 128 [](int a) { return a; }, 129 []<class T>(T c) { return c * 2; }, 130 }; 131 132 EXPECT_EQ(7, overloaded(7)); 133 EXPECT_EQ(14.0, overloaded(7.0)); 134 } 135 136 #endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L 137 138 TEST(OverloadTest, DispatchConsidersSfinae) { 139 auto overloaded = absl::Overload{ 140 [](auto a) -> decltype(a + 1) { return a + 1; }, 141 }; 142 143 static_assert(std::is_invocable_v<decltype(overloaded), int>); 144 static_assert(!std::is_invocable_v<decltype(overloaded), std::string>); 145 } 146 147 TEST(OverloadTest, VariantVisitDispatchesCorrectly) { 148 absl::variant<int, double, std::string> v(1); 149 auto overloaded = absl::Overload{ 150 [](int) -> absl::string_view { return "int"; }, 151 [](double) -> absl::string_view { return "double"; }, 152 [](const std::string&) -> absl::string_view { return "string"; }, 153 }; 154 155 EXPECT_EQ("int", absl::visit(overloaded, v)); 156 v = 1.1; 157 EXPECT_EQ("double", absl::visit(overloaded, v)); 158 v = "hello"; 159 EXPECT_EQ("string", absl::visit(overloaded, v)); 160 } 161 162 TEST(OverloadTest, VariantVisitWithAutoFallbackDispatchesCorrectly) { 163 absl::variant<std::string, int32_t, int64_t> v(int32_t{1}); 164 auto overloaded = absl::Overload{ 165 [](const std::string& s) { return s.size(); }, 166 [](const auto& s) { return sizeof(s); }, 167 }; 168 169 EXPECT_EQ(4, absl::visit(overloaded, v)); 170 v = int64_t{1}; 171 EXPECT_EQ(8, absl::visit(overloaded, v)); 172 v = std::string("hello"); 173 EXPECT_EQ(5, absl::visit(overloaded, v)); 174 } 175 176 // This API used to be exported as a function, so it should also work fine to 177 // use parantheses when initializing it. 178 TEST(OverloadTest, UseWithParentheses) { 179 const auto overloaded = 180 absl::Overload([](const std::string& s) { return s.size(); }, 181 [](const auto& s) { return sizeof(s); }); 182 183 absl::variant<std::string, int32_t, int64_t> v(int32_t{1}); 184 EXPECT_EQ(4, absl::visit(overloaded, v)); 185 186 v = int64_t{1}; 187 EXPECT_EQ(8, absl::visit(overloaded, v)); 188 189 v = std::string("hello"); 190 EXPECT_EQ(5, absl::visit(overloaded, v)); 191 } 192 193 TEST(OverloadTest, HasConstexprConstructor) { 194 constexpr auto overloaded = absl::Overload{ 195 [](int v) { return absl::StrCat("int ", v); }, 196 [](double v) { return absl::StrCat("double ", v); }, 197 [](const char* v) { return absl::StrCat("const char* ", v); }, 198 [](auto v) { return absl::StrCat("auto ", v); }, 199 }; 200 201 EXPECT_EQ("int 1", overloaded(1)); 202 EXPECT_EQ("double 2.5", overloaded(2.5)); 203 EXPECT_EQ("const char* hello", overloaded("hello")); 204 EXPECT_EQ("auto 1.5", overloaded(1.5f)); 205 } 206 207 } // namespace