Skip to content

Commit df73616

Browse files
authored
is(): correct is() for types (#1204)
* Remove invalid check Non-polymorphic types cannot be casted with dynamic_cast * Remove dead code std::is_polymorphic_v<X> when X is pointer returns false that means that later std::is_pointer_v<X> will always be false * Remove extra parens * Fix formating * Add test for is with polymorphic types * is(): add support for pointers Support for is<X*>(ptr) * Update of tests to support is() with pointers * is(): add support for nullptr_t * is(): add test for nullptr_t * Add tests against unrelated type * is(): made is() compile-time when possible * is(): fix test when is() returns std::bool_constant * Fix polymorphic tests * Remove empty .cpp.output files
1 parent 873b760 commit df73616

18 files changed

+279
-22
lines changed

include/cpp2util.h

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,39 +1635,44 @@ constexpr auto is( X&& ) {
16351635
// Types
16361636
//
16371637
template< typename C, typename X >
1638-
auto is( X const& x ) -> bool {
1638+
constexpr auto is( X const& x ) -> auto {
16391639
if constexpr (
16401640
std::is_same_v<C, X>
16411641
|| std::is_base_of_v<C, X>
16421642
)
16431643
{
1644-
return true;
1644+
return std::true_type{};
16451645
}
16461646
else if constexpr (
1647-
std::is_base_of_v<X, C>
1648-
|| (
1649-
std::is_polymorphic_v<C>
1650-
&& std::is_polymorphic_v<X>
1651-
)
1647+
std::is_polymorphic_v<C>
1648+
&& std::is_polymorphic_v<X>
16521649
)
16531650
{
1654-
if constexpr (std::is_pointer_v<X>) {
1655-
return Dynamic_cast<C const*>(x) != nullptr;
1656-
}
1657-
else {
1658-
return Dynamic_cast<C const*>(&x) != nullptr;
1659-
}
1651+
return Dynamic_cast<C const*>(&x) != nullptr;
16601652
}
16611653
else if constexpr (
1662-
requires { *x; X(); }
1654+
(
1655+
std::is_same_v<X, std::nullptr_t>
1656+
|| requires { *x; X(); }
1657+
)
16631658
&& std::is_same_v<C, empty>
16641659
)
16651660
{
16661661
return x == X();
16671662
}
1668-
else {
1663+
else if constexpr (
1664+
std::is_pointer_v<C>
1665+
&& std::is_pointer_v<X>
1666+
)
1667+
{
1668+
if (x != nullptr) {
1669+
return bool{is<std::remove_pointer_t<C>>(*x)};
1670+
}
16691671
return false;
16701672
}
1673+
else {
1674+
return std::false_type{};
1675+
}
16711676
}
16721677

16731678

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ class Square : public Shape { };
1010

1111
//--- printing helpers -----------------
1212

13-
print: ( msg: std::string, x: _ ) =
13+
print: <T : type> ( msg: std::string, x: T )
14+
requires !std::convertible_to<T, bool> =
1415
std::cout << msg << x << "\n";
1516

1617
print: ( msg: std::string, b: bool ) =
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
A: type = {}
2+
3+
VA: @polymorphic_base <I:int> type = {}
4+
5+
VC: type = {
6+
this: VA<0>;
7+
this: VA<1>;
8+
}
9+
10+
VD: type = {
11+
this: VA<0>;
12+
}
13+
14+
fun: (v, name) = {
15+
std::cout << "(name)$ is";
16+
if v is VC { std::cout << " VC"; }
17+
if v is VA<0> { std::cout << " VA<0>"; }
18+
if v is VA<1> { std::cout << " VA<1>"; }
19+
if v is VD { std::cout << " VD"; }
20+
if v is *VC { std::cout << " *VC"; }
21+
if v is *VA<0> { std::cout << " *VA<0>"; }
22+
if v is *VA<1> { std::cout << " *VA<1>"; }
23+
if v is *VD { std::cout << " *VD"; }
24+
if v is void { std::cout << " empty"; }
25+
if v is A { std::cout << " A"; }
26+
std::cout << std::endl;
27+
}
28+
29+
main: () = {
30+
31+
vc : VC = ();
32+
p0 : *VA<0> = vc&;
33+
p1 : *VA<1> = vc&;
34+
35+
fun(vc, "vc");
36+
fun(p0*, "p0*");
37+
fun(p1*, "p1*");
38+
39+
fun(vc&, "vc&");
40+
fun(p0, "p0");
41+
fun(p1, "p1");
42+
43+
fun(nullptr, "nullptr");
44+
fun(A(), "A");
45+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A

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

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,13 @@ class Square : public Shape { };
2424
//--- printing helpers -----------------
2525

2626
#line 13 "mixed-type-safety-1.cpp2"
27-
auto print(cpp2::impl::in<std::string> msg, auto const& x) -> void;
27+
template<typename T> auto print(cpp2::impl::in<std::string> msg, T const& x) -> void
28+
CPP2_REQUIRES (!(std::convertible_to<T,bool>)) ;
2829

29-
#line 16 "mixed-type-safety-1.cpp2"
30+
#line 17 "mixed-type-safety-1.cpp2"
3031
auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void;
3132

32-
#line 24 "mixed-type-safety-1.cpp2"
33+
#line 25 "mixed-type-safety-1.cpp2"
3334
//--- examples -------------------------
3435

3536
[[nodiscard]] auto main() -> int;
@@ -39,10 +40,13 @@ auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void;
3940
#line 1 "mixed-type-safety-1.cpp2"
4041

4142
#line 13 "mixed-type-safety-1.cpp2"
42-
auto print(cpp2::impl::in<std::string> msg, auto const& x) -> void {
43+
template<typename T> auto print(cpp2::impl::in<std::string> msg, T const& x) -> void
44+
requires (!(std::convertible_to<T,bool>)) {
45+
46+
#line 15 "mixed-type-safety-1.cpp2"
4347
std::cout << msg << x << "\n"; }
4448

45-
#line 16 "mixed-type-safety-1.cpp2"
49+
#line 17 "mixed-type-safety-1.cpp2"
4650
auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void
4751
{
4852
cpp2::impl::deferred_init<char const*> bmsg;
@@ -51,7 +55,7 @@ auto print(cpp2::impl::in<std::string> msg, cpp2::impl::in<bool> b) -> void
5155
std::cout << msg << cpp2::move(bmsg.value()) << "\n";
5256
}
5357

54-
#line 26 "mixed-type-safety-1.cpp2"
58+
#line 27 "mixed-type-safety-1.cpp2"
5559
[[nodiscard]] auto main() -> int
5660
{
5761
print("1.1 is int? ", cpp2::impl::is<int>(1.1));
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
vc is VC VA<0> VA<1>
2+
p0* is VC VA<0> VA<1>
3+
p1* is VC VA<0> VA<1>
4+
vc& is *VC *VA<0> *VA<1>
5+
p0 is *VC *VA<0> *VA<1>
6+
p1 is *VC *VA<0> *VA<1>
7+
nullptr is empty
8+
A is A
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
2+
#define CPP2_IMPORT_STD Yes
3+
4+
//=== Cpp2 type declarations ====================================================
5+
6+
7+
#include "cpp2util.h"
8+
9+
#line 1 "pure2-is-with-polymorphic-types.cpp2"
10+
class A;
11+
#line 2 "pure2-is-with-polymorphic-types.cpp2"
12+
13+
template<int I> class VA;
14+
15+
class VC;
16+
17+
18+
#line 10 "pure2-is-with-polymorphic-types.cpp2"
19+
class VD;
20+
21+
22+
//=== Cpp2 type definitions and function declarations ===========================
23+
24+
#line 1 "pure2-is-with-polymorphic-types.cpp2"
25+
class A {
26+
public: A() = default;
27+
public: A(A const&) = delete; /* No 'that' constructor, suppress copy */
28+
public: auto operator=(A const&) -> void = delete;
29+
};
30+
#line 2 "pure2-is-with-polymorphic-types.cpp2"
31+
32+
template<int I> class VA {
33+
public: virtual ~VA() noexcept;
34+
35+
public: VA() = default;
36+
public: VA(VA const&) = delete; /* No 'that' constructor, suppress copy */
37+
public: auto operator=(VA const&) -> void = delete;
38+
};
39+
#line 4 "pure2-is-with-polymorphic-types.cpp2"
40+
41+
class VC: public VA<0>, public VA<1> {
42+
public: VC() = default;
43+
public: VC(VC const&) = delete; /* No 'that' constructor, suppress copy */
44+
public: auto operator=(VC const&) -> void = delete;
45+
46+
47+
#line 8 "pure2-is-with-polymorphic-types.cpp2"
48+
};
49+
50+
class VD: public VA<0> {
51+
public: VD() = default;
52+
public: VD(VD const&) = delete; /* No 'that' constructor, suppress copy */
53+
public: auto operator=(VD const&) -> void = delete;
54+
55+
56+
#line 12 "pure2-is-with-polymorphic-types.cpp2"
57+
};
58+
59+
auto fun(auto const& v, auto const& name) -> void;
60+
61+
#line 29 "pure2-is-with-polymorphic-types.cpp2"
62+
auto main() -> int;
63+
64+
//=== Cpp2 function definitions =================================================
65+
66+
#line 1 "pure2-is-with-polymorphic-types.cpp2"
67+
68+
69+
template <int I> VA<I>::~VA() noexcept{}
70+
#line 14 "pure2-is-with-polymorphic-types.cpp2"
71+
auto fun(auto const& v, auto const& name) -> void{
72+
std::cout << "" + cpp2::to_string(name) + " is";
73+
if (cpp2::impl::is<VC>(v)) {std::cout << " VC";}
74+
if (cpp2::impl::is<VA<0>>(v)) {std::cout << " VA<0>";}
75+
if (cpp2::impl::is<VA<1>>(v)) {std::cout << " VA<1>";}
76+
if (cpp2::impl::is<VD>(v)) {std::cout << " VD";}
77+
if (cpp2::impl::is<VC*>(v)) {std::cout << " *VC";}
78+
if (cpp2::impl::is<VA<0>*>(v)) {std::cout << " *VA<0>";}
79+
if (cpp2::impl::is<VA<1>*>(v)) {std::cout << " *VA<1>";}
80+
if (cpp2::impl::is<VD*>(v)) {std::cout << " *VD";}
81+
if (cpp2::impl::is<void>(v)) {std::cout << " empty";}
82+
if (cpp2::impl::is<A>(v)) {std::cout << " A";}
83+
std::cout << std::endl;
84+
}
85+
86+
#line 29 "pure2-is-with-polymorphic-types.cpp2"
87+
auto main() -> int{
88+
89+
VC vc {};
90+
VA<0>* p0 {&vc};
91+
VA<1>* p1 {&vc};
92+
93+
fun(vc, "vc");
94+
fun(*cpp2::impl::assert_not_null(p0), "p0*");
95+
fun(*cpp2::impl::assert_not_null(p1), "p1*");
96+
97+
fun(&vc, "vc&");
98+
fun(cpp2::move(p0), "p0");
99+
fun(cpp2::move(p1), "p1");
100+
101+
fun(nullptr, "nullptr");
102+
fun(A(), "A");
103+
}
104+
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
pure2-is-with-polymorphic-types.cpp2... ok (all Cpp2, passes safety checks)
2+

0 commit comments

Comments
 (0)