Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions csrc/polymorphic_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,7 @@ class StructHandle {
inline StructType type() const;

template <typename Ret, typename Class>
inline std::enable_if_t<std::is_base_of_v<Struct, Class>, Ret&> operator->*(
Ret Class::* member) const {
inline Ret& operator->*(Ret Class::* member) const {
return as<Class>().*member;
}

Expand Down
195 changes: 98 additions & 97 deletions lib/dynamic_type/src/dynamic_type/dynamic_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#pragma once

#include <algorithm>
#include <concepts>
#include <cstddef>
#include <initializer_list>
#include <optional>
Expand Down Expand Up @@ -247,13 +248,11 @@ struct DynamicType {
template <typename T, typename = decltype(VariantType(std::declval<T>()))>
constexpr DynamicType(T&& value) : value(std::forward<T>(value)) {}

template <
template <typename...> typename Template,
typename ItemT,
typename = std::enable_if_t<
is_candidate_type<Template<DynamicType>> &&
!std::is_same_v<ItemT, DynamicType>>>
constexpr DynamicType(Template<ItemT> value)
template <template <typename...> typename Template, typename ItemT>
requires(
is_candidate_type<Template<DynamicType>> &&
!std::is_same_v<ItemT, DynamicType>) constexpr DynamicType(Template<ItemT>
value)
: value([](auto input) {
Template<DynamicType> result;
std::transform(
Expand All @@ -264,14 +263,13 @@ struct DynamicType {
return result;
}(std::move(value))) {}

template <
typename ItemT = DynamicType,
typename = std::enable_if_t<
// enable this ctor only when there is only one container supporting
// initializer_list, otherwise it is ambiguous to tell which container
// to use.
num_container_types_constructible_from_initializer_list<ItemT> == 1>>
constexpr DynamicType(std::initializer_list<DynamicType> list)
template <typename ItemT = DynamicType>
requires(
// enable this ctor only when there is only one container supporting
// initializer_list, otherwise it is ambiguous to tell which container
// to use.
num_container_types_constructible_from_initializer_list<ItemT> ==
1) constexpr DynamicType(std::initializer_list<DynamicType> list)
: DynamicType(typename std::tuple_element_t<
0,
AllContainerTypeIdentitiesConstructibleFromInitializerList<
Expand Down Expand Up @@ -303,32 +301,32 @@ struct DynamicType {
return !isNull();
}

template <typename T, typename = std::enable_if_t<is_candidate_type<T>>>
constexpr const T& as() const {
template <typename T>
requires is_candidate_type<T> constexpr const T& as() const {
return std::get<T>(value);
}

template <typename T, typename = std::enable_if_t<is_candidate_type<T>>>
constexpr T& as() {
template <typename T>
requires is_candidate_type<T> constexpr T& as() {
return std::get<T>(value);
}

template <
template <typename...> typename Template,
typename = std::enable_if_t<is_candidate_type<Template<DynamicType>>>>
constexpr const Template<DynamicType>& as() const {
template <template <typename...> typename Template>
requires is_candidate_type<Template<DynamicType>> constexpr const Template<
DynamicType>&
as() const {
return as<Template<DynamicType>>();
}

template <
template <typename...> typename Template,
typename = std::enable_if_t<is_candidate_type<Template<DynamicType>>>>
constexpr Template<DynamicType>& as() {
template <template <typename...> typename Template>
requires is_candidate_type<Template<DynamicType>> constexpr Template<
DynamicType>&
as() {
return as<Template<DynamicType>>();
}

template <typename T, typename = std::enable_if_t<can_cast_to<T>>>
explicit constexpr operator T() const {
template <typename T>
requires can_cast_to<T> explicit constexpr operator T() const {
return dispatch(
[](auto x) -> decltype(auto) {
using X = decltype(x);
Expand All @@ -339,12 +337,10 @@ struct DynamicType {
*this);
}

template <
template <typename...> typename Template,
typename ItemT,
typename = std::enable_if_t<
is_candidate_type<Template<DynamicType>> && can_cast_to<ItemT>>>
explicit constexpr operator Template<ItemT>() const {
template <template <typename...> typename Template, typename ItemT>
requires(is_candidate_type<Template<DynamicType>>&&
can_cast_to<ItemT>) explicit constexpr
operator Template<ItemT>() const {
DYNAMIC_TYPE_CHECK(
is<Template<DynamicType>>(),
"Cannot cast from ",
Expand Down Expand Up @@ -402,10 +398,9 @@ struct DynamicType {

#define DEFINE_SQUARE_BRACKET_OPERATOR(__const) \
template <typename IndexT> \
std::enable_if_t< \
!std::is_same_v<IndexT, DynamicType> && has_square_bracket<IndexT>, \
__const DynamicType&> \
operator[](const IndexT& i) __const { \
requires(!std::is_same_v<IndexT, DynamicType> && has_square_bracket<IndexT>) \
__const DynamicType& \
operator[](const IndexT& i) __const { \
std::optional<std::reference_wrapper<__const DynamicType>> ret = \
std::nullopt; \
for_all_types([this, &ret, &i](auto t) { \
Expand Down Expand Up @@ -443,10 +438,9 @@ struct DynamicType {

#define DEFINE_SQUARE_BRACKET_OPERATOR(__const) \
template <typename DT> \
std::enable_if_t< \
std::is_same_v<DT, DynamicType> && has_any_square_bracket, \
__const DynamicType&> \
operator[](const DT& i) __const { \
requires(std::is_same_v<DT, DynamicType>&& has_any_square_bracket) \
__const DynamicType& \
operator[](const DT& i) __const { \
std::optional<std::reference_wrapper<__const DynamicType>> ret = \
std::nullopt; \
for_all_types([this, &ret, &i](auto t) { \
Expand Down Expand Up @@ -479,11 +473,9 @@ struct DynamicType {
// example: use (abc->*A::print)() instead of abc->*A::print().

#define DEFINE_ARROW_STAR_OPERATOR(__const) \
template < \
typename Ret, \
typename Class, \
typename = std::enable_if_t<is_candidate_type<Class>>> \
constexpr decltype(auto) operator->*(Ret Class::* member) __const { \
template <typename Ret, typename Class> \
requires is_candidate_type<Class> constexpr decltype(auto) operator->*( \
Ret Class::* member) __const { \
/* Use decltype(auto) instead of auto as return type so that references */ \
/* and qualifiers are preserved*/ \
if constexpr (std::is_function_v<Ret>) { \
Expand All @@ -509,7 +501,7 @@ struct DynamicType {
static constexpr auto all_arrow_star_ret_types##__const = \
remove_void_from_tuple(for_all_types([](auto t) { \
using T = typename decltype(t)::type; \
if constexpr (opcheck<T>->*opcheck<MemberT>) { \
if constexpr (requires(T t, MemberT m) { t->*m; }) { \
return std::type_identity< \
decltype(std::declval<__const T>()->*std::declval<MemberT>())>{}; \
} \
Expand All @@ -528,15 +520,32 @@ struct DynamicType {
typename first_or_void<AllArrowStarRetTypes##__const<MemberT>>::type; \
\
template <typename MemberT> \
constexpr std::enable_if_t< \
all_arrow_star_ret_types_are_same##__const<MemberT>, \
typename ArrowStarRetType##__const<MemberT>::type> \
operator->*(const MemberT& member) __const { \
using RetT = typename ArrowStarRetType##__const<MemberT>::type; \
static constexpr bool has_valid_arrow_star_ret_type##__const = \
!std::is_void_v<ArrowStarRetType##__const<MemberT>>; \
\
/* Helper to safely extract type from ArrowStarRetType */ \
template <typename MemberT, typename = void> \
struct ArrowStarRetTypeExtractor##__const { \
using type = void; \
}; \
\
template <typename MemberT> \
struct ArrowStarRetTypeExtractor##__const< \
MemberT, \
std::enable_if_t<has_valid_arrow_star_ret_type##__const<MemberT>>> { \
using type = typename ArrowStarRetType##__const<MemberT>::type; \
}; \
\
template <typename MemberT> \
requires(all_arrow_star_ret_types_are_same##__const<MemberT>&& \
has_valid_arrow_star_ret_type##__const<MemberT>) constexpr \
typename ArrowStarRetTypeExtractor##__const<MemberT>::type \
operator->*(const MemberT& member) __const { \
using RetT = typename ArrowStarRetTypeExtractor##__const<MemberT>::type; \
std::optional<wrap_reference_t<RetT>> ret = std::nullopt; \
for_all_types([this, &member, &ret](auto t) { \
using T = typename decltype(t)::type; \
if constexpr (opcheck<T>->*opcheck<MemberT>) { \
if constexpr (requires(T t, MemberT m) { t->*m; }) { \
if (is<T>()) { \
ret = as<T>()->*member; \
} \
Expand Down Expand Up @@ -622,9 +631,9 @@ constexpr bool is_dynamic_type_v = is_dynamic_type<T>::value;
typename DT = std::conditional_t< \
is_dynamic_type_v<std::decay_t<LHS>>, \
std::decay_t<LHS>, \
std::decay_t<RHS>>, \
typename = std::enable_if_t<opname##_defined<LHS, RHS>()>> \
inline constexpr return_type func_name(LHS&& x, RHS&& y) { \
std::decay_t<RHS>>> \
requires(opname##_defined<LHS, RHS>()) inline constexpr return_type \
func_name(LHS&& x, RHS&& y) { \
constexpr bool lhs_is_dt = is_dynamic_type_v<std::decay_t<LHS>>; \
constexpr bool rhs_is_dt = is_dynamic_type_v<std::decay_t<RHS>>; \
if constexpr ( \
Expand Down Expand Up @@ -709,13 +718,12 @@ DEFINE_BINARY_OP(ge, >=, operator>=, bool, false);
constexpr auto opname##_helper = [](auto x) constexpr { \
return (op opcheck<typename decltype(x)::type>); \
}; \
template < \
typename DT, \
typename = std::enable_if_t< \
is_dynamic_type_v<std::decay_t<DT>> && \
any_check( \
opname##_helper, std::decay_t<DT>::type_identities_as_tuple)>> \
inline constexpr decltype(auto) operator op(DT&& x) { \
template <typename DT> \
requires(is_dynamic_type_v<std::decay_t<DT>>&& any_check( \
opname##_helper, \
std::decay_t< \
DT>::type_identities_as_tuple)) inline constexpr decltype(auto) \
operator op(DT&& x) { \
return std::decay_t<DT>::dispatch( \
[](auto&& x) -> decltype(auto) { \
if constexpr (op opcheck<std::decay_t<decltype(x)>>) { \
Expand Down Expand Up @@ -747,12 +755,11 @@ auto star_defined_checker = [](auto t) {
return false;
};

template <
typename DT,
typename = std::enable_if_t<
is_dynamic_type_v<DT> &&
any_check(star_defined_checker<DT>, DT::type_identities_as_tuple)>>
DT& operator*(const DT& x) {
template <typename DT>
requires(is_dynamic_type_v<DT>&& any_check(
star_defined_checker<DT>,
DT::type_identities_as_tuple)) DT&
operator*(const DT& x) {
std::optional<std::reference_wrapper<DT>> ret = std::nullopt;
DT::for_all_types([&ret, &x](auto t) {
using T = typename decltype(t)::type;
Expand Down Expand Up @@ -780,12 +787,11 @@ constexpr auto can_print = [](auto x) constexpr {
}
return false;
};
template <
typename DT,
typename = std::enable_if_t<
is_dynamic_type_v<DT> &&
any_check(can_print, DT::type_identities_as_tuple)>>
std::ostream& operator<<(std::ostream& os, const DT& dt) {
template <typename DT>
requires(is_dynamic_type_v<DT>&& any_check(
can_print,
DT::type_identities_as_tuple)) std::ostream&
operator<<(std::ostream& os, const DT& dt) {
bool printed = false;
DT::for_all_types([&printed, &os, &dt](auto _) {
using T = typename decltype(_)::type;
Expand Down Expand Up @@ -815,12 +821,10 @@ std::ostream& operator<<(std::ostream& os, const DT& dt) {
} \
return false; \
}; \
template < \
typename DT, \
typename = std::enable_if_t< \
is_dynamic_type_v<DT> && \
any_check(opname##_helper, DT::type_identities_as_tuple)>> \
inline constexpr DT& operator op(DT & x) { \
template <typename DT> \
requires(is_dynamic_type_v<DT>&& any_check( \
opname##_helper, DT::type_identities_as_tuple)) inline constexpr DT& \
operator op(DT & x) { \
bool computed = false; \
DT::for_all_types([&computed, &x](auto _) { \
using Type = typename decltype(_)::type; \
Expand Down Expand Up @@ -862,12 +866,10 @@ DEFINE_LEFT_PPMM(lmm, --);
return false; \
}; \
template <typename DT> \
inline constexpr std::enable_if_t< \
is_dynamic_type_v<DT> && \
any_check( \
opname##_helper<typename DT::VariantType>, \
DT::type_identities_as_tuple), \
DT> operator op(DT & x, int) { \
requires(is_dynamic_type_v<DT>&& any_check( \
opname##_helper<typename DT::VariantType>, \
DT::type_identities_as_tuple)) inline constexpr DT \
operator op(DT& x, int) { \
DT ret; \
DT::for_all_types([&ret, &x](auto _) { \
using Type = typename decltype(_)::type; \
Expand Down Expand Up @@ -895,14 +897,13 @@ DEFINE_RIGHT_PPMM(rmm, --);

#undef DEFINE_RIGHT_PPMM

#define DEFINE_ASSIGNMENT_OP(op, assign_op) \
template < \
typename DT, \
typename T, \
typename = std::enable_if_t< \
is_dynamic_type_v<DT> && (opcheck<DT> op opcheck<T>)>> \
inline constexpr DT& operator assign_op(DT & x, const T & y) { \
return x = x op y; \
#define DEFINE_ASSIGNMENT_OP(op, assign_op) \
template <typename DT, typename T> \
requires( \
is_dynamic_type_v<DT> && \
(opcheck<DT> op opcheck<T>)) inline constexpr DT& \
operator assign_op(DT & x, const T & y) { \
return x = x op y; \
}

DEFINE_ASSIGNMENT_OP(+, +=);
Expand Down
Loading
Loading