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 "absl/base/config.h"
22 #include "absl/strings/str_cat.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/types/variant.h"
25
26 #if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \
27 ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L
28
29 #include "gtest/gtest.h"
30
31 namespace {
32
TEST(OverloadTest,DispatchConsidersTypeWithAutoFallback)33 TEST(OverloadTest, DispatchConsidersTypeWithAutoFallback) {
34 auto overloaded = absl::Overload(
35 [](int v) -> std::string { return absl::StrCat("int ", v); }, //
36 [](double v) -> std::string { return absl::StrCat("double ", v); }, //
37 [](const char* v) -> std::string { //
38 return absl::StrCat("const char* ", v); //
39 }, //
40 [](auto v) -> std::string { return absl::StrCat("auto ", v); } //
41 );
42 EXPECT_EQ("int 1", overloaded(1));
43 EXPECT_EQ("double 2.5", overloaded(2.5));
44 EXPECT_EQ("const char* hello", overloaded("hello"));
45 EXPECT_EQ("auto 1.5", overloaded(1.5f));
46 }
47
TEST(OverloadTest,DispatchConsidersNumberOfArguments)48 TEST(OverloadTest, DispatchConsidersNumberOfArguments) {
49 auto overloaded = absl::Overload( //
50 [](int a) { return a + 1; }, //
51 [](int a, int b) { return a * b; }, //
52 []() -> absl::string_view { return "none"; } //
53 );
54 EXPECT_EQ(3, overloaded(2));
55 EXPECT_EQ(21, overloaded(3, 7));
56 EXPECT_EQ("none", overloaded());
57 }
58
TEST(OverloadTest,SupportsConstantEvaluation)59 TEST(OverloadTest, SupportsConstantEvaluation) {
60 auto overloaded = absl::Overload( //
61 [](int a) { return a + 1; }, //
62 [](int a, int b) { return a * b; }, //
63 []() -> absl::string_view { return "none"; } //
64 );
65 static_assert(overloaded() == "none");
66 static_assert(overloaded(2) == 3);
67 static_assert(overloaded(3, 7) == 21);
68 }
69
TEST(OverloadTest,PropogatesDefaults)70 TEST(OverloadTest, PropogatesDefaults) {
71 auto overloaded = absl::Overload( //
72 [](int a, int b = 5) { return a * b; }, //
73 [](double c) { return c; } //
74 );
75
76 EXPECT_EQ(21, overloaded(3, 7));
77 EXPECT_EQ(35, overloaded(7));
78 EXPECT_EQ(2.5, overloaded(2.5));
79 }
80
TEST(OverloadTest,AmbiguousWithDefaultsNotInvocable)81 TEST(OverloadTest, AmbiguousWithDefaultsNotInvocable) {
82 auto overloaded = absl::Overload( //
83 [](int a, int b = 5) { return a * b; }, //
84 [](int c) { return c; } //
85 );
86 static_assert(!std::is_invocable_v<decltype(overloaded), int>);
87 static_assert(std::is_invocable_v<decltype(overloaded), int, int>);
88 }
89
TEST(OverloadTest,AmbiguousDuplicatesNotInvocable)90 TEST(OverloadTest, AmbiguousDuplicatesNotInvocable) {
91 auto overloaded = absl::Overload( //
92 [](int a) { return a; }, //
93 [](int c) { return c; } //
94 );
95 static_assert(!std::is_invocable_v<decltype(overloaded), int>);
96 }
97
TEST(OverloadTest,AmbiguousConversionNotInvocable)98 TEST(OverloadTest, AmbiguousConversionNotInvocable) {
99 auto overloaded = absl::Overload( //
100 [](uint16_t a) { return a; }, //
101 [](uint64_t c) { return c; } //
102 );
103 static_assert(!std::is_invocable_v<decltype(overloaded), int>);
104 }
105
TEST(OverloadTest,AmbiguousConversionWithAutoNotInvocable)106 TEST(OverloadTest, AmbiguousConversionWithAutoNotInvocable) {
107 auto overloaded = absl::Overload( //
108 [](auto a) { return a; }, //
109 [](auto c) { return c; } //
110 );
111 static_assert(!std::is_invocable_v<decltype(overloaded), int>);
112 }
113
114 #if ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
115
TEST(OverloadTest,AmbiguousConversionWithAutoAndTemplateNotInvocable)116 TEST(OverloadTest, AmbiguousConversionWithAutoAndTemplateNotInvocable) {
117 auto overloaded = absl::Overload( //
118 [](auto a) { return a; }, //
119 []<class T>(T c) { return c; } //
120 );
121 static_assert(!std::is_invocable_v<decltype(overloaded), int>);
122 }
123
TEST(OverloadTest,DispatchConsidersTypeWithTemplateFallback)124 TEST(OverloadTest, DispatchConsidersTypeWithTemplateFallback) {
125 auto overloaded = absl::Overload( //
126 [](int a) { return a; }, //
127 []<class T>(T c) { return c * 2; } //
128 );
129 EXPECT_EQ(7, overloaded(7));
130 EXPECT_EQ(14.0, overloaded(7.0));
131 }
132
133 #endif // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L
134
TEST(OverloadTest,DispatchConsidersSfinae)135 TEST(OverloadTest, DispatchConsidersSfinae) {
136 auto overloaded = absl::Overload( //
137 [](auto a) -> decltype(a + 1) { return a + 1; } //
138 );
139 static_assert(std::is_invocable_v<decltype(overloaded), int>);
140 static_assert(!std::is_invocable_v<decltype(overloaded), std::string>);
141 }
142
TEST(OverloadTest,VariantVisitDispatchesCorrectly)143 TEST(OverloadTest, VariantVisitDispatchesCorrectly) {
144 absl::variant<int, double, std::string> v(1);
145 auto overloaded = absl::Overload(
146 [](int) -> absl::string_view { return "int"; }, //
147 [](double) -> absl::string_view { return "double"; }, //
148 [](const std::string&) -> absl::string_view { return "string"; } //
149 );
150 EXPECT_EQ("int", absl::visit(overloaded, v));
151 v = 1.1;
152 EXPECT_EQ("double", absl::visit(overloaded, v));
153 v = "hello";
154 EXPECT_EQ("string", absl::visit(overloaded, v));
155 }
156
TEST(OverloadTest,VariantVisitWithAutoFallbackDispatchesCorrectly)157 TEST(OverloadTest, VariantVisitWithAutoFallbackDispatchesCorrectly) {
158 absl::variant<std::string, int32_t, int64_t> v(int32_t{1});
159 auto overloaded = absl::Overload(
160 [](const std::string& s) { return s.size(); }, //
161 [](const auto& s) { return sizeof(s); } //
162 );
163 EXPECT_EQ(4, absl::visit(overloaded, v));
164 v = int64_t{1};
165 EXPECT_EQ(8, absl::visit(overloaded, v));
166 v = std::string("hello");
167 EXPECT_EQ(5, absl::visit(overloaded, v));
168 }
169
170 } // namespace
171
172 #endif
173