You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Extension of is() part1: free function predicates, fix implicit cast for build-in and custom is operator, refactoring (#1053)
* Extend is() to handle free function predicates
This change address to issues:
1. implicit downcasting of arguments,
2. add support for predicates with generic type argument
1. Currently, if is() is checked against predicate the predicate argument
can be implicitly casted that can lead to downcasting double to int
equal_pi: (x:int) -> bool = { return x == 3; };
d := 3.14;
if d is (equal_pi) { // d will be casted to int and will return true
// ...
}
After this change downcasting will not happen no false positive/negative
matches will happen.
2. Currently, if is() is checked against predicate with generic type
it does not compile.
After this change the code will compile and work as expected.
* Add test for is with unnamed predicates
Adding test for using is with lambdas, and generic lambdas.
* Rewrite is() for variables and templates
Adjust to new style of using one function for a match and series
of constexpr ifs.
There is a possibility to extend is() for matching std::integer_sequence
but unfortunatelly clang is not support it (gcc & msvc do).
template <template <typename, typename, typename...> class C, typename X>
constexpr auto is( X const& ) {
if constexpr (specialization_of_template<X, C>) {
return std::true_type{};
}
else {
return std::false_type{};
}
}
template <template <typename, auto...> class C, typename X>
constexpr auto is( X const& ) {
if constexpr (specialization_of_template_type_and_nttp<X, C>) {
return std::true_type{};
}
else {
return std::false_type{};
}
}
Alternatively we can support more matches for gcc & msvc by providing:
#if defined(__clang__)
template <template <typename...> class C, typename X>
#else
// allow us to support std::integer_sequence on gcc and msvc
template <template <typename, typename, typename...> class C, typename X>
#endif
constexpr auto is( X const& ) {
if constexpr (specialization_of_template<X, C>) {
return std::true_type{};
}
else {
return std::false_type{};
}
}
#if defined(__clang__)
template <template <typename, auto> class C, typename X>
#else
// allow us to support std::integer_sequence on gcc and msvc
template <template <typename, auto...> class C, typename X>
#endif
constexpr auto is( X const& ) {
if constexpr (specialization_of_template_type_and_nttp<X, C>) {
return std::true_type{};
}
else {
return std::false_type{};
}
}
* Extend is() to correctly handle custom is operator
In current implementation custom is operator (`is_op()` member function)
suffers from implicit casting of its argument. The same issue that were
with function predicates.
After this change we added the check if the cast is lossless or
if the custom is operator is generic function.
Added tests to verify is with various values.
Added new concepts to make checks more readable:
- valid_custom_is_operator
- defined - to check if type is defined (used to determined generic fun)
- predicate_member_fun - to check if member function is a predicate,
Added new type trait:
- argument_of_op_is_t to determined the type of op_is argument,
Correct helper methods:
- argument_of_helper - to handle ref-qualified member functions,
- argument_of_helper - to work with non-copyable types,
* Did two minor tweaks, and updated tests
Add an array value-equality case (thanks to MSVC for warning about that)
Also stop forwarding the `value` to `std::vformat` to stay compatible with the `vformat` change
---------
Co-authored-by: Herb Sutter <[email protected]>
0 commit comments