Skip to content

Commit

Permalink
is(): correct is() for types (#1204)
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
filipsajdak committed Aug 10, 2024
1 parent 873b760 commit df73616
Show file tree
Hide file tree
Showing 18 changed files with 279 additions and 22 deletions.
35 changes: 20 additions & 15 deletions include/cpp2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -1635,39 +1635,44 @@ constexpr auto is( X&& ) {
// Types
//
template< typename C, typename X >
auto is( X const& x ) -> bool {
constexpr auto is( X const& x ) -> auto {
if constexpr (
std::is_same_v<C, X>
|| std::is_base_of_v<C, X>
)
{
return true;
return std::true_type{};
}
else if constexpr (
std::is_base_of_v<X, C>
|| (
std::is_polymorphic_v<C>
&& std::is_polymorphic_v<X>
)
std::is_polymorphic_v<C>
&& std::is_polymorphic_v<X>
)
{
if constexpr (std::is_pointer_v<X>) {
return Dynamic_cast<C const*>(x) != nullptr;
}
else {
return Dynamic_cast<C const*>(&x) != nullptr;
}
return Dynamic_cast<C const*>(&x) != nullptr;
}
else if constexpr (
requires { *x; X(); }
(
std::is_same_v<X, std::nullptr_t>
|| requires { *x; X(); }
)
&& std::is_same_v<C, empty>
)
{
return x == X();
}
else {
else if constexpr (
std::is_pointer_v<C>
&& std::is_pointer_v<X>
)
{
if (x != nullptr) {
return bool{is<std::remove_pointer_t<C>>(*x)};
}
return false;
}
else {
return std::false_type{};
}
}


Expand Down
3 changes: 2 additions & 1 deletion regression-tests/mixed-type-safety-1.cpp2
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ class Square : public Shape { };

//--- printing helpers -----------------

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

print: ( msg: std::string, b: bool ) =
Expand Down
45 changes: 45 additions & 0 deletions regression-tests/pure2-is-with-polymorphic-types.cpp2
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
A: type = {}

VA: @polymorphic_base <I:int> type = {}

VC: type = {
this: VA<0>;
this: VA<1>;
}

VD: type = {
this: VA<0>;
}

fun: (v, name) = {
std::cout << "(name)$ is";
if v is VC { std::cout << " VC"; }
if v is VA<0> { std::cout << " VA<0>"; }
if v is VA<1> { std::cout << " VA<1>"; }
if v is VD { std::cout << " VD"; }
if v is *VC { std::cout << " *VC"; }
if v is *VA<0> { std::cout << " *VA<0>"; }
if v is *VA<1> { std::cout << " *VA<1>"; }
if v is *VD { std::cout << " *VD"; }
if v is void { std::cout << " empty"; }
if v is A { std::cout << " A"; }
std::cout << std::endl;
}

main: () = {

vc : VC = ();
p0 : *VA<0> = vc&;
p1 : *VA<1> = vc&;

fun(vc, "vc");
fun(p0*, "p0*");
fun(p1*, "p1*");

fun(vc&, "vc&");
fun(p0, "p0");
fun(p1, "p1");

fun(nullptr, "nullptr");
fun(A(), "A");
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
16 changes: 10 additions & 6 deletions regression-tests/test-results/mixed-type-safety-1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ class Square : public Shape { };
//--- printing helpers -----------------

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

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

#line 24 "mixed-type-safety-1.cpp2"
#line 25 "mixed-type-safety-1.cpp2"
//--- examples -------------------------

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

#line 13 "mixed-type-safety-1.cpp2"
auto print(cpp2::impl::in<std::string> msg, auto const& x) -> void {
template<typename T> auto print(cpp2::impl::in<std::string> msg, T const& x) -> void
requires (!(std::convertible_to<T,bool>)) {

#line 15 "mixed-type-safety-1.cpp2"
std::cout << msg << x << "\n"; }

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

#line 26 "mixed-type-safety-1.cpp2"
#line 27 "mixed-type-safety-1.cpp2"
[[nodiscard]] auto main() -> int
{
print("1.1 is int? ", cpp2::impl::is<int>(1.1));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
vc is VC VA<0> VA<1>
p0* is VC VA<0> VA<1>
p1* is VC VA<0> VA<1>
vc& is *VC *VA<0> *VA<1>
p0 is *VC *VA<0> *VA<1>
p1 is *VC *VA<0> *VA<1>
nullptr is empty
A is A
104 changes: 104 additions & 0 deletions regression-tests/test-results/pure2-is-with-polymorphic-types.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@

#define CPP2_IMPORT_STD Yes

//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

#line 1 "pure2-is-with-polymorphic-types.cpp2"
class A;
#line 2 "pure2-is-with-polymorphic-types.cpp2"

template<int I> class VA;

class VC;


#line 10 "pure2-is-with-polymorphic-types.cpp2"
class VD;


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

#line 1 "pure2-is-with-polymorphic-types.cpp2"
class A {
public: A() = default;
public: A(A const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(A const&) -> void = delete;
};
#line 2 "pure2-is-with-polymorphic-types.cpp2"

template<int I> class VA {
public: virtual ~VA() noexcept;

public: VA() = default;
public: VA(VA const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(VA const&) -> void = delete;
};
#line 4 "pure2-is-with-polymorphic-types.cpp2"

class VC: public VA<0>, public VA<1> {
public: VC() = default;
public: VC(VC const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(VC const&) -> void = delete;


#line 8 "pure2-is-with-polymorphic-types.cpp2"
};

class VD: public VA<0> {
public: VD() = default;
public: VD(VD const&) = delete; /* No 'that' constructor, suppress copy */
public: auto operator=(VD const&) -> void = delete;


#line 12 "pure2-is-with-polymorphic-types.cpp2"
};

auto fun(auto const& v, auto const& name) -> void;

#line 29 "pure2-is-with-polymorphic-types.cpp2"
auto main() -> int;

//=== Cpp2 function definitions =================================================

#line 1 "pure2-is-with-polymorphic-types.cpp2"


template <int I> VA<I>::~VA() noexcept{}
#line 14 "pure2-is-with-polymorphic-types.cpp2"
auto fun(auto const& v, auto const& name) -> void{
std::cout << "" + cpp2::to_string(name) + " is";
if (cpp2::impl::is<VC>(v)) {std::cout << " VC";}
if (cpp2::impl::is<VA<0>>(v)) {std::cout << " VA<0>";}
if (cpp2::impl::is<VA<1>>(v)) {std::cout << " VA<1>";}
if (cpp2::impl::is<VD>(v)) {std::cout << " VD";}
if (cpp2::impl::is<VC*>(v)) {std::cout << " *VC";}
if (cpp2::impl::is<VA<0>*>(v)) {std::cout << " *VA<0>";}
if (cpp2::impl::is<VA<1>*>(v)) {std::cout << " *VA<1>";}
if (cpp2::impl::is<VD*>(v)) {std::cout << " *VD";}
if (cpp2::impl::is<void>(v)) {std::cout << " empty";}
if (cpp2::impl::is<A>(v)) {std::cout << " A";}
std::cout << std::endl;
}

#line 29 "pure2-is-with-polymorphic-types.cpp2"
auto main() -> int{

VC vc {};
VA<0>* p0 {&vc};
VA<1>* p1 {&vc};

fun(vc, "vc");
fun(*cpp2::impl::assert_not_null(p0), "p0*");
fun(*cpp2::impl::assert_not_null(p1), "p1*");

fun(&vc, "vc&");
fun(cpp2::move(p0), "p0");
fun(cpp2::move(p1), "p1");

fun(nullptr, "nullptr");
fun(A(), "A");
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
pure2-is-with-polymorphic-types.cpp2... ok (all Cpp2, passes safety checks)

0 comments on commit df73616

Please sign in to comment.