Skip to content

Commit

Permalink
is()/as(): refactor of is() and as() for std::any and std::optional t…
Browse files Browse the repository at this point in the history
…o new design (part 3 of n) (hsutter#1251)

* is()/as(): Refactor is() and as() for std::any

* is()/as(): refactor is() and as() for std::optional

* Fix tests
  • Loading branch information
filipsajdak authored Sep 3, 2024
1 parent a18d22e commit 2949161
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 72 deletions.
72 changes: 36 additions & 36 deletions include/cpp2util.h
Original file line number Diff line number Diff line change
Expand Up @@ -2083,28 +2083,22 @@ auto as(X&& x CPP2_SOURCE_LOCATION_PARAM_WITH_DEFAULT_AS) -> decltype(auto)

// is Type
//
template<typename T, typename X>
requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty>)
constexpr auto is( X const& x ) -> bool
{ return x.type() == Typeid<T>(); }

template<typename T, typename X>
requires (std::is_same_v<X,std::any> && std::is_same_v<T,empty>)
constexpr auto is( X const& x ) -> bool
{ return !x.has_value(); }

template<typename T, std::same_as<std::any> X>
constexpr auto is( X const& x ) -> bool{
if (!x.has_value()) {
return std::is_same_v<T,empty>;
}
return x.type() == Typeid<T>();
}

// is Value
//
inline constexpr auto is( std::any const& x, auto&& value ) -> bool
{
// Predicate case
if constexpr (requires{ bool{ value(x) }; }) {
if constexpr (valid_predicate<decltype(value), decltype(x)>) {
return value(x);
}
else if constexpr (std::is_function_v<decltype(value)> || requires{ &value.operator(); }) {
return false;
}

// Value case
else if constexpr (requires{ bool{ *std::any_cast<CPP2_TYPEOF(value)>(&x) == value }; }) {
Expand All @@ -2118,10 +2112,12 @@ inline constexpr auto is( std::any const& x, auto&& value ) -> bool

// as
//
template<typename T, typename X>
requires (!std::is_reference_v<T> && std::is_same_v<X,std::any> && !std::is_same_v<T,std::any>)
constexpr auto as( X const& x ) -> T
{ return std::any_cast<T>( x ); }
template<typename T, same_type_as<std::any> X>
constexpr auto as( X && x ) -> decltype(auto) {
constness_like_t<T, X>* ptr = std::any_cast<T>( &x );
if (!ptr) { Throw( std::bad_any_cast(), "'as' cast failed for 'std::any'"); }
return cpp2::forward_like<X>(*ptr);
}


//-------------------------------------------------------------------------------------------------------------
Expand All @@ -2130,29 +2126,26 @@ constexpr auto as( X const& x ) -> T

// is Type
//
template<typename T, typename X>
requires std::is_same_v<X,std::optional<T>>
constexpr auto is( X const& x ) -> bool
{ return x.has_value(); }

template<typename T, typename U>
requires std::is_same_v<T,empty>
constexpr auto is( std::optional<U> const& x ) -> bool
{ return !x.has_value(); }

template<typename T, specialization_of_template<std::optional> X>
constexpr auto is( X const& x ) -> bool {
if (!x.has_value()) {
return std::same_as<T, empty>;
}
if constexpr (requires { static_cast<const T&>(*x);}) {
return true;
}
return false;
}

// is Value
//
template<typename T>
constexpr auto is( std::optional<T> const& x, auto&& value ) -> bool
{
// Predicate case
if constexpr (requires{ bool{ value(x) }; }) {
if constexpr (valid_predicate<decltype(value), decltype(x)>) {
return value(x);
}
else if constexpr (std::is_function_v<decltype(value)> || requires{ &value.operator(); }) {
return false;
}

// Value case
else if constexpr (requires{ bool{ x.value() == value }; }) {
Expand All @@ -2164,10 +2157,17 @@ constexpr auto is( std::optional<T> const& x, auto&& value ) -> bool

// as
//
template<typename T, typename X>
requires std::is_same_v<X,std::optional<T>>
constexpr auto as( X const& x ) -> decltype(auto)
{ return x.value(); }
template<typename T, specialization_of_template<std::optional> X>
constexpr auto as( X&& x ) -> decltype(auto) {
constness_like_t<T, X>* ptr = nullptr;
if constexpr (requires { static_cast<constness_like_t<T, X>&>(*x); }) {
if (x.has_value()) {
ptr = &static_cast<constness_like_t<T, X>&>(*x);
}
}
if (!ptr) { Throw( std::bad_optional_access(), "'as' cast failed for 'std::optional'"); }
return cpp2::forward_like<X>(*ptr);
}


} // impl
Expand Down
Original file line number Diff line number Diff line change
@@ -1,66 +1,66 @@
In file included from pure2-default-arguments.cpp:7:
../../../include/cpp2util.h:2086:28: error: local variable ‘obj’ may not appear in this context
2086 | template<typename T, typename X>
2086 | template<typename T, std::same_as<std::any> X>
| ^~~
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
| ^
../../../include/cpp2util.h:2086:15: note: in expansion of macro ‘CPP2_FORWARD’
2086 | template<typename T, typename X>
2086 | template<typename T, std::same_as<std::any> X>
| ^~~~~~~~~~~~
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2086:92: error: local variable ‘params’ may not appear in this context
2086 | template<typename T, typename X>
2086 | template<typename T, std::same_as<std::any> X>
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
| ^
../../../include/cpp2util.h:2086:79: note: in expansion of macro ‘CPP2_FORWARD’
2086 | template<typename T, typename X>
2086 | template<typename T, std::same_as<std::any> X>
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2087:74: error: local variable ‘obj’ may not appear in this context
2087 | requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty>)
| ^~~
2087 | constexpr auto is( X const& x ) -> bool{
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
| ^
../../../include/cpp2util.h:2087:61: note: in expansion of macro ‘CPP2_FORWARD’
2087 | requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty>)
| ^~~~~~~~~~~~
2087 | constexpr auto is( X const& x ) -> bool{
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
../../../include/cpp2util.h:2087:93: error: local variable ‘params’ may not appear in this context
2087 | requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty>)
| ^~~~~~
2087 | constexpr auto is( X const& x ) -> bool{
| ^
../../../include/cpp2util.h:2047:34: note: in definition of macro ‘CPP2_UFCS_IDENTITY’
2047 | return false;
| ^
../../../include/cpp2util.h:2087:80: note: in expansion of macro ‘CPP2_FORWARD’
2087 | requires (std::is_same_v<X,std::any> && !std::is_same_v<T,std::any> && !std::is_same_v<T,empty>)
| ^~~~~~~~~~~~
2087 | constexpr auto is( X const& x ) -> bool{
| ^
../../../include/cpp2util.h:2107:22: note: in expansion of macro ‘CPP2_UFCS_CONSTRAINT_ARG’
2107 | }
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
pure2-default-arguments.cpp2:6:22: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
pure2-default-arguments.cpp2:6:61: error: ‘std::source_location’ has not been declared
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
In file included from mixed-bugfix-for-ufcs-non-local.cpp:6:
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
Original file line number Diff line number Diff line change
@@ -1,41 +1,41 @@
In file included from mixed-bugfix-for-ufcs-non-local.cpp:6:
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:13:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:13:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:31:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:31:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:33:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:33:36: error: template argument 1 is invalid
../../../include/cpp2util.h:2100:1: error: lambda-expression in template parameter type
2100 | {
2100 | return value(x);
| ^
../../../include/cpp2util.h:2137:59: note: in expansion of macro ‘CPP2_UFCS_’
2137 |
2137 | return false;
| ^
mixed-bugfix-for-ufcs-non-local.cpp2:21:12: note: in expansion of macro ‘CPP2_UFCS_NONLOCAL’
mixed-bugfix-for-ufcs-non-local.cpp2:21:36: error: template argument 1 is invalid

0 comments on commit 2949161

Please sign in to comment.