Skip to content

Commit df73616

Browse files
authored
is(): correct is() for types (hsutter#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

0 commit comments

Comments
 (0)