Skip to content

Commit c57e3b6

Browse files
committed
CompareRecursive fix for GCC-12
Fixed comparison of C-style strings, char arrays and string literals
1 parent e58cf9f commit c57e3b6

3 files changed

Lines changed: 96 additions & 11 deletions

File tree

ut/utils_comparison.h

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,15 @@ ::testing::AssertionResult CompareCotainersRecursive(const LeftContainer& left,
141141
template <typename Container>
142142
struct PrintContainer;
143143

144+
144145
template <typename Left, typename Right>
145146
::testing::AssertionResult CompareRecursive(const Left & left, const Right & right) {
146-
if constexpr (!is_string_v<Left> && !is_string_v<Right>
147-
&& (is_container_v<Left> || std::is_base_of_v<clickhouse::Column, std::decay_t<Left>>)
148-
&& (is_container_v<Right> || std::is_base_of_v<clickhouse::Column, std::decay_t<Right>>) ) {
147+
using L = std::decay_t<Left>;
148+
using R = std::decay_t<Right>;
149+
150+
if constexpr (!is_string_v<L> && !is_string_v<R>
151+
&& (is_container_v<L> || std::is_base_of_v<clickhouse::Column, L>)
152+
&& (is_container_v<R> || std::is_base_of_v<clickhouse::Column, R>) ) {
149153

150154
const auto & l = maybeWrapColumnAsContainer(left);
151155
const auto & r = maybeWrapColumnAsContainer(right);
@@ -155,24 +159,29 @@ ::testing::AssertionResult CompareRecursive(const Left & left, const Right & rig
155159
else
156160
return result << "\nExpected container: " << PrintContainer{l}
157161
<< "\nActual container : " << PrintContainer{r};
162+
}
163+
else if constexpr (std::is_same_v<char const *, L> || std::is_same_v<char *, L>) {
164+
return CompareRecursive(std::string_view(left), right);
165+
}
166+
else if constexpr (std::is_same_v<char const *, R> || std::is_same_v<char *, R>) {
167+
return CompareRecursive(left, std::string_view(right));
158168
} else {
159169
if (left != right) {
160-
161170
// Handle std::optional<float>(nan)
162-
// I'm too lazy to code comparison against std::nullopt, but this shpudn't be a problem in real life.
163-
// RN comparing against std::nullopt, you'll receive an compilation error.
164-
if constexpr (is_instantiation_of<std::optional, Left>::value && is_instantiation_of<std::optional, Right>::value)
171+
// I'm too lazy to code comparison against std::nullopt, but this shouldn't be a problem in real life.
172+
// RN comparing against std::nullopt, you'll get a compilation error.
173+
if constexpr (is_instantiation_of<std::optional, L>::value && is_instantiation_of<std::optional, R>::value)
165174
{
166175
if (left.has_value() && right.has_value())
167176
return CompareRecursive(*left, *right);
168177
}
169-
else if constexpr (is_instantiation_of<std::optional, Left>::value) {
178+
else if constexpr (is_instantiation_of<std::optional, L>::value) {
170179
if (left)
171180
return CompareRecursive(*left, right);
172-
} else if constexpr (is_instantiation_of<std::optional, Right>::value) {
181+
} else if constexpr (is_instantiation_of<std::optional, R>::value) {
173182
if (right)
174183
return CompareRecursive(left, *right);
175-
} else if constexpr (std::is_floating_point_v<Left> && std::is_floating_point_v<Right>) {
184+
} else if constexpr (std::is_floating_point_v<L> && std::is_floating_point_v<R>) {
176185
if (std::isnan(left) && std::isnan(right))
177186
return ::testing::AssertionSuccess();
178187
}

ut/utils_meta.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct is_instantiation_of< Template, Template<Args...> > : std::true_type {};
5252
template <typename T>
5353
inline constexpr bool is_string_v = std::is_same_v<std::string, std::decay_t<T>> || std::is_same_v<std::string_view, std::decay_t<T>>;
5454

55+
5556
// https://stackoverflow.com/a/34111095
5657
template <typename...>
5758
struct is_one_of {

ut/utils_ut.cpp

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,84 @@ TEST(CompareRecursive, CompareValues) {
1212
EXPECT_TRUE(CompareRecursive(1.0, 1.0));
1313
EXPECT_TRUE(CompareRecursive(1.0L, 1.0L));
1414

15+
EXPECT_TRUE(CompareRecursive('a', 'a'));
16+
}
17+
18+
TEST(CompareRecursive, CompareStrings) {
19+
// literals
1520
EXPECT_TRUE(CompareRecursive("1.0L", "1.0L"));
16-
EXPECT_TRUE(CompareRecursive(std::string{"1.0L"}, std::string{"1.0L"}));
21+
EXPECT_TRUE(CompareRecursive("1.0L", std::string("1.0L")));
22+
EXPECT_TRUE(CompareRecursive(std::string("1.0L"), "1.0L"));
23+
EXPECT_TRUE(CompareRecursive("1.0L", std::string_view("1.0L")));
24+
EXPECT_TRUE(CompareRecursive(std::string_view("1.0L"), "1.0L"));
25+
26+
// array
27+
const char str[] = "1.0L";
28+
EXPECT_TRUE(CompareRecursive("1.0L", str));
29+
EXPECT_TRUE(CompareRecursive(str, "1.0L"));
30+
EXPECT_TRUE(CompareRecursive(str, str));
31+
EXPECT_TRUE(CompareRecursive(str, std::string("1.0L")));
32+
EXPECT_TRUE(CompareRecursive(std::string("1.0L"), str));
33+
EXPECT_TRUE(CompareRecursive(str, std::string_view("1.0L")));
34+
EXPECT_TRUE(CompareRecursive(std::string_view("1.0L"), str));
35+
36+
// pointer
37+
const char *str2 = "1.0L";
38+
EXPECT_TRUE(CompareRecursive("1.0L", str2));
39+
EXPECT_TRUE(CompareRecursive(str2, "1.0L"));
40+
EXPECT_TRUE(CompareRecursive(str2, str2));
41+
EXPECT_TRUE(CompareRecursive(str2, str));
42+
EXPECT_TRUE(CompareRecursive(str, str2));
43+
EXPECT_TRUE(CompareRecursive(str2, std::string("1.0L")));
44+
EXPECT_TRUE(CompareRecursive(std::string("1.0L"), str2));
45+
EXPECT_TRUE(CompareRecursive(str2, std::string_view("1.0L")));
46+
EXPECT_TRUE(CompareRecursive(std::string_view("1.0L"), str2));
47+
48+
// string & string_view
49+
EXPECT_TRUE(CompareRecursive(std::string{"1.0L"}, std::string{"1.0L"}));
1750
EXPECT_TRUE(CompareRecursive(std::string_view{"1.0L"}, std::string_view{"1.0L"}));
51+
EXPECT_TRUE(CompareRecursive(std::string{"1.0L"}, std::string_view{"1.0L"}));
52+
EXPECT_TRUE(CompareRecursive(std::string_view{"1.0L"}, std::string{"1.0L"}));
53+
}
54+
55+
TEST(CompareRecursive, CompareContainerOfStrings) {
56+
const std::vector<const char*> vector_of_cstrings = {
57+
"abc",
58+
"cde",
59+
"ghi"
60+
};
61+
62+
const std::vector<std::string> vector_of_strings = {
63+
"abc",
64+
"cde",
65+
"ghi"
66+
};
67+
68+
const std::vector<std::string_view> vector_of_string_views = {
69+
"abc",
70+
"cde",
71+
"ghi"
72+
};
73+
74+
{
75+
// same values, but different pointers
76+
const std::vector<const char*> vector_of_cstrings2 = {
77+
vector_of_strings[0].data(),
78+
vector_of_strings[1].data(),
79+
vector_of_strings[2].data(),
80+
};
81+
EXPECT_TRUE(CompareRecursive(vector_of_cstrings, vector_of_cstrings2));
82+
}
83+
84+
EXPECT_TRUE(CompareRecursive(vector_of_strings, vector_of_strings));
85+
EXPECT_TRUE(CompareRecursive(vector_of_strings, vector_of_cstrings));
86+
EXPECT_TRUE(CompareRecursive(vector_of_cstrings, vector_of_strings));
87+
88+
EXPECT_TRUE(CompareRecursive(vector_of_string_views, vector_of_string_views));
89+
EXPECT_TRUE(CompareRecursive(vector_of_strings, vector_of_string_views));
90+
EXPECT_TRUE(CompareRecursive(vector_of_string_views, vector_of_strings));
91+
EXPECT_TRUE(CompareRecursive(vector_of_strings, vector_of_string_views));
92+
EXPECT_TRUE(CompareRecursive(vector_of_string_views, vector_of_strings));
1893
}
1994

2095
TEST(CompareRecursive, CompareContainers) {

0 commit comments

Comments
 (0)