Skip to content

Commit 2a44c4b

Browse files
mihaiboroshsutter
andauthored
1328 Fixed issue comparing different numerical types as equal. (#1365)
* 1328 Fixed issue comparing different numerical types as equal. * 1328 Added back type comparison in case of inheritance. * Add regression test cases --------- Signed-off-by: Herb Sutter <herb.sutter@gmail.com> Co-authored-by: Herb Sutter <herb.sutter@gmail.com>
1 parent 496b75d commit 2a44c4b

File tree

8 files changed

+98
-10
lines changed

8 files changed

+98
-10
lines changed

include/cpp2util.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2102,10 +2102,8 @@ constexpr auto is( X const& x ) -> bool {
21022102
if (!x.has_value()) {
21032103
return std::same_as<T, empty>;
21042104
}
2105-
if constexpr (requires { static_cast<const T&>(*x);}) {
2106-
return true;
2107-
}
2108-
return false;
2105+
return std::same_as<T, typename X::value_type>
2106+
|| std::derived_from<std::remove_pointer_t<typename X::value_type>, std::remove_pointer_t<T>>;
21092107
}
21102108

21112109
// is Value

regression-tests/pure2-type-safety-1.cpp2

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ main: () -> int =
1919
test_generic(v, "variant<int, int, double>");
2020
test_generic(a, "any");
2121
test_generic(o, "optional<int>");
22+
23+
oi: std::optional<int> = 5;
24+
std::cout << "optional<int> is: ";
25+
test_1365(oi);
26+
od: std::optional<*D> = nullptr;
27+
std::cout << "\noptional<*D> is: ";
28+
test_1365(od);
29+
std::cout << "\n";
2230
}
2331

2432
test_generic: ( x, msg ) = {
@@ -28,6 +36,30 @@ test_generic: ( x, msg ) = {
2836
::print( msgx + " is int? ", x is int );
2937
}
3038

39+
B: type = { }
40+
D: type = { this: B; }
41+
42+
test_1365: (o) = {
43+
if o is int {
44+
std::cout << "int ";
45+
}
46+
if o is bool {
47+
std::cout << "bool ";
48+
}
49+
if o is float {
50+
std::cout << "float ";
51+
}
52+
if o is *B {
53+
std::cout << "*B ";
54+
}
55+
if o is *D {
56+
std::cout << "*D ";
57+
}
58+
if o is std::string {
59+
std::cout << "std::string ";
60+
}
61+
}
62+
3163
print: ( msg: std::string, b: bool ) = {
3264
bmsg: * const char;
3365
if b { bmsg = "true"; }

regression-tests/test-results/clang-12-c++20/pure2-type-safety-1.cpp.execution

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
variant<int, int, double> is int? true
88
any is int? true
99
optional<int> is int? true
10+
optional<int> is: int
11+
optional<*D> is: *B *D

regression-tests/test-results/gcc-10-c++20/pure2-type-safety-1.cpp.execution

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
variant<int, int, double> is int? true
88
any is int? true
99
optional<int> is int? true
10+
optional<int> is: int
11+
optional<*D> is: *B *D

regression-tests/test-results/gcc-14-c++2b/pure2-type-safety-1.cpp.execution

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
variant<int, int, double> is int? true
88
any is int? true
99
optional<int> is int? true
10+
optional<int> is: int
11+
optional<*D> is: *B *D

regression-tests/test-results/msvc-2022-c++latest/pure2-type-safety-1.cpp.execution

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
variant<int, int, double> is int? true
88
any is int? true
99
optional<int> is int? true
10+
optional<int> is: int
11+
optional<*D> is: *B *D

regression-tests/test-results/pure2-type-safety-1.cpp

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88

99
#line 1 "pure2-type-safety-1.cpp2"
1010

11+
#line 39 "pure2-type-safety-1.cpp2"
12+
class B;
13+
class D;
14+
1115

1216
//=== Cpp2 type definitions and function declarations ===========================
1317

@@ -16,12 +20,28 @@
1620
#line 2 "pure2-type-safety-1.cpp2"
1721
[[nodiscard]] auto main() -> int;
1822

19-
#line 24 "pure2-type-safety-1.cpp2"
23+
#line 32 "pure2-type-safety-1.cpp2"
2024
auto test_generic(auto const& x, auto const& msg) -> void;
2125

22-
#line 31 "pure2-type-safety-1.cpp2"
26+
#line 39 "pure2-type-safety-1.cpp2"
27+
class B {
28+
public: B() = default;
29+
public: B(B const&) = delete; /* No 'that' constructor, suppress copy */
30+
public: auto operator=(B const&) -> void = delete;
31+
};
32+
#line 40 "pure2-type-safety-1.cpp2"
33+
class D: public B {
34+
public: D() = default;
35+
public: D(D const&) = delete; /* No 'that' constructor, suppress copy */
36+
public: auto operator=(D const&) -> void = delete;
37+
};
38+
#line 41 "pure2-type-safety-1.cpp2"
39+
40+
auto test_1365(auto const& o) -> void;
41+
42+
#line 63 "pure2-type-safety-1.cpp2"
2343
auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void;
24-
#line 37 "pure2-type-safety-1.cpp2"
44+
#line 69 "pure2-type-safety-1.cpp2"
2545

2646
#line 1 "pure2-type-safety-1.cpp2"
2747

@@ -50,17 +70,47 @@ auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void;
5070
test_generic(cpp2::move(v), "variant<int, int, double>");
5171
test_generic(cpp2::move(a), "any");
5272
test_generic(cpp2::move(o), "optional<int>");
73+
74+
std::optional<int> oi {5};
75+
std::cout << "optional<int> is: ";
76+
test_1365(cpp2::move(oi));
77+
std::optional<D*> od {nullptr};
78+
std::cout << "\noptional<*D> is: ";
79+
test_1365(cpp2::move(od));
80+
std::cout << "\n";
5381
}
5482

55-
#line 24 "pure2-type-safety-1.cpp2"
83+
#line 32 "pure2-type-safety-1.cpp2"
5684
auto test_generic(auto const& x, auto const& msg) -> void{
5785
std::string msgx {msg};
5886
// Full qualification is necessary to avoid ambiguity in C++23
5987
// C++23 defines std::print, which would be picked up here by ADL
6088
::print(cpp2::move(msgx) + " is int? ", cpp2::impl::is<int>(x));
6189
}
6290

63-
#line 31 "pure2-type-safety-1.cpp2"
91+
#line 42 "pure2-type-safety-1.cpp2"
92+
auto test_1365(auto const& o) -> void{
93+
if (cpp2::impl::is<int>(o)) {
94+
std::cout << "int ";
95+
}
96+
if (cpp2::impl::is<bool>(o)) {
97+
std::cout << "bool ";
98+
}
99+
if (cpp2::impl::is<float>(o)) {
100+
std::cout << "float ";
101+
}
102+
if (cpp2::impl::is<B*>(o)) {
103+
std::cout << "*B ";
104+
}
105+
if (cpp2::impl::is<D*>(o)) {
106+
std::cout << "*D ";
107+
}
108+
if (cpp2::impl::is<std::string>(o)) {
109+
std::cout << "std::string ";
110+
}
111+
}
112+
113+
#line 63 "pure2-type-safety-1.cpp2"
64114
auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void{
65115
cpp2::impl::deferred_init<char const*> bmsg;
66116
if (b) { bmsg.construct("true");}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11

2-
cppfront compiler v0.8.1 Build A206:0852
2+
cppfront compiler v0.8.1 Build 10202:1808
33
SPDX-License-Identifier Apache-2.0 WITH LLVM-exception
44
Copyright (c) 2022-2024 Herb Sutter

0 commit comments

Comments
 (0)