Commit f360df15 authored by Dominik Charousset's avatar Dominik Charousset

pattern matching

parent cc1c3445
...@@ -78,7 +78,8 @@ class tpartial_function ...@@ -78,7 +78,8 @@ class tpartial_function
tpartial_function(tpartial_function const&) = default; tpartial_function(tpartial_function const&) = default;
bool defined_at(typename util::rm_ref<Args>::type const&... args) const //bool defined_at(typename util::rm_ref<Args>::type const&... args) const
bool defined_at(Args... args) const
{ {
return m_guard(args...); return m_guard(args...);
} }
......
...@@ -143,8 +143,8 @@ template<typename Result, typename F, ...@@ -143,8 +143,8 @@ template<typename Result, typename F,
template<typename...> class Tuple, typename... T> template<typename...> class Tuple, typename... T>
Result unchecked_apply_tuple(F&& fun, Tuple<T...>& tup) Result unchecked_apply_tuple(F&& fun, Tuple<T...>& tup)
{ {
return unchecked_apply_tuple_in_range<Result, 0, sizeof...(T) - 1> return apply_tuple_util<Result, true, 0, sizeof...(T) - 1>
(std::forward<F>(fun), tup); ::apply(std::forward<F>(fun), tup);
} }
} } // namespace cppa::util } } // namespace cppa::util
......
...@@ -133,7 +133,8 @@ struct is_callable ...@@ -133,7 +133,8 @@ struct is_callable
static void _fun(void*) { } static void _fun(void*) { }
typedef decltype(_fun(static_cast<T*>(nullptr))) result_type; typedef decltype(_fun(static_cast<typename rm_ref<T>::type*>(nullptr)))
result_type;
public: public:
......
...@@ -76,8 +76,11 @@ bool compare_tuples(LhsTuple<LhsTypes...> const& lhs, ...@@ -76,8 +76,11 @@ bool compare_tuples(LhsTuple<LhsTypes...> const& lhs,
static_assert(sizeof...(LhsTypes) == sizeof...(RhsTypes), static_assert(sizeof...(LhsTypes) == sizeof...(RhsTypes),
"could not compare tuples of different size"); "could not compare tuples of different size");
static_assert(tl_zipped_forall<type_list<type_pair<LhsTypes,RhsTypes>...>, static_assert(tl_binary_forall<
is_comparable>::value, type_list<LhsTypes...>,
type_list<RhsTypes...>,
is_comparable
>::value,
"types of lhs are not comparable to the types of rhs"); "types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(sizeof...(LhsTypes) - 1), return detail::cmp_helper<(sizeof...(LhsTypes) - 1),
...@@ -90,20 +93,16 @@ template<template<typename...> class LhsTuple, typename... LhsTypes, ...@@ -90,20 +93,16 @@ template<template<typename...> class LhsTuple, typename... LhsTypes,
bool compare_first_elements(LhsTuple<LhsTypes...> const& lhs, bool compare_first_elements(LhsTuple<LhsTypes...> const& lhs,
RhsTuple<RhsTypes...> const& rhs) RhsTuple<RhsTypes...> const& rhs)
{ {
static constexpr size_t cmp_size = (sizeof...(LhsTypes) < sizeof...(RhsTypes)) typedef typename tl_zip<
? sizeof...(LhsTypes) util::type_list<LhsTypes...>,
: sizeof...(RhsTypes); util::type_list<RhsTypes...>
>::type
zipped_types;
typedef util::type_list<LhsTypes...> lhs_tlist; static_assert(tl_zipped_forall<zipped_types, is_comparable>::value,
typedef util::type_list<RhsTypes...> rhs_tlist;
typedef typename tl_first_n<lhs_tlist, cmp_size>::type lhs_sublist;
typedef typename tl_first_n<rhs_tlist, cmp_size>::type rhs_sublist;
typedef typename tl_zip<lhs_sublist, rhs_sublist>::type zipped_sublists;
static_assert(tl_zipped_forall<zipped_sublists, is_comparable>::value,
"types of lhs are not comparable to the types of rhs"); "types of lhs are not comparable to the types of rhs");
return detail::cmp_helper<(cmp_size - 1), return detail::cmp_helper<(zipped_types::size - 1),
LhsTuple<LhsTypes...>, LhsTuple<LhsTypes...>,
RhsTuple<RhsTypes...>>::cmp(lhs, rhs); RhsTuple<RhsTypes...>>::cmp(lhs, rhs);
} }
......
...@@ -101,7 +101,87 @@ struct is_type_list<type_list<Ts...> > ...@@ -101,7 +101,87 @@ struct is_type_list<type_list<Ts...> >
static constexpr bool value = true; static constexpr bool value = true;
}; };
// static list zip(list, list) // list slice(size_t, size_t)
template<size_t LeftOffset, size_t Remaining,
typename PadType, class List, typename... T>
struct tl_slice_impl
{
typedef typename tl_slice_impl<
LeftOffset - 1,
Remaining,
PadType,
typename List::tail,
T...
>::type
type;
};
template<size_t Remaining, typename PadType, class List, typename... T>
struct tl_slice_impl<0, Remaining, PadType, List, T...>
{
typedef typename tl_slice_impl<
0,
Remaining - 1,
PadType,
typename List::tail,
T..., typename List::head
>::type
type;
};
template<size_t Remaining, typename PadType, typename... T>
struct tl_slice_impl<0, Remaining, PadType, type_list<>, T...>
{
typedef typename tl_slice_impl<
0,
Remaining - 1,
PadType,
type_list<>,
T..., PadType
>::type
type;
};
template<typename PadType, class List, typename... T>
struct tl_slice_impl<0, 0, PadType, List, T...>
{
typedef type_list<T...> type;
};
template<typename PadType, typename... T>
struct tl_slice_impl<0, 0, PadType, type_list<>, T...>
{
typedef type_list<T...> type;
};
template<class List, size_t ListSize, size_t First, size_t Last,
typename PadType = void_type>
struct tl_slice_
{
typedef typename tl_slice_impl<
First,
(Last - First),
PadType, List
>::type
type;
};
template<class List, size_t ListSize, typename PadType>
struct tl_slice_<List, ListSize, 0, ListSize, PadType>
{
typedef List type;
};
/**
* @brief Creates a new list from range (First, Last].
*/
template<class List, size_t First, size_t Last>
struct tl_slice
{
static_assert(First <= Last, "First > Last");
typedef typename tl_slice_<List, List::size, First, Last>::type type;
};
/** /**
* @brief Zips two lists of equal size. * @brief Zips two lists of equal size.
...@@ -112,11 +192,11 @@ struct is_type_list<type_list<Ts...> > ...@@ -112,11 +192,11 @@ struct is_type_list<type_list<Ts...> >
*/ */
template<class ListA, class ListB, template<class ListA, class ListB,
template<typename, typename> class Fun = to_type_pair> template<typename, typename> class Fun = to_type_pair>
struct tl_zip; struct tl_zip_impl;
template<typename... LhsElements, typename... RhsElements, template<typename... LhsElements, typename... RhsElements,
template<typename, typename> class Fun> template<typename, typename> class Fun>
struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...>, Fun> struct tl_zip_impl<type_list<LhsElements...>, type_list<RhsElements...>, Fun>
{ {
static_assert(sizeof...(LhsElements) == static_assert(sizeof...(LhsElements) ==
sizeof...(RhsElements), sizeof...(RhsElements),
...@@ -124,6 +204,51 @@ struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...>, Fun> ...@@ -124,6 +204,51 @@ struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...>, Fun>
typedef type_list<typename Fun<LhsElements, RhsElements>::type...> type; typedef type_list<typename Fun<LhsElements, RhsElements>::type...> type;
}; };
template<class ListA, class ListB,
template<typename, typename> class Fun = to_type_pair>
struct tl_zip
{
static constexpr size_t result_size =
(ListA::size < ListB::size) ? ListA::size
: ListB::size;
typedef typename tl_zip_impl<
typename tl_slice<ListA, 0, result_size>::type,
typename tl_slice<ListB, 0, result_size>::type,
Fun
>::type
type;
};
template<class ListA,
class ListB,
typename PadA = void_type,
typename PadB = void_type,
template<typename, typename> class Fun = to_type_pair>
struct tl_zip_all
{
static constexpr size_t result_size =
(ListA::size > ListB::size) ? ListA::size
: ListB::size;
typedef typename tl_zip_impl<
typename tl_slice_<
ListA,
ListA::size,
0,
result_size
>::type,
typename tl_slice_<
ListB,
ListB::size,
0,
result_size
>::type,
Fun
>::type
type;
};
template<class ListA> template<class ListA>
struct tl_unzip; struct tl_unzip;
...@@ -240,102 +365,53 @@ struct tl_find_if ...@@ -240,102 +365,53 @@ struct tl_find_if
static constexpr int value = tl_find_impl<List, Predicate, Pos>::value; static constexpr int value = tl_find_impl<List, Predicate, Pos>::value;
}; };
// list first_n(size_t) // bool forall(predicate)
template<size_t N, class List, typename... T>
struct tl_first_n_impl
{
typedef typename tl_first_n_impl<
N - 1,
typename List::tail,
T..., typename List::head
>::type
type;
};
template<class List, typename... T>
struct tl_first_n_impl<0, List, T...>
{
typedef type_list<T...> type;
};
/** /**
* @brief Creates a new list from the first @p N elements of @p List. * @brief Tests whether a predicate holds for all elements of a list.
*/ */
template<class List, size_t N> template<class List, template<typename> class Predicate>
struct tl_first_n struct tl_forall
{
static_assert(List::size >= N, "List::size < N");
typedef typename tl_first_n_impl<N, List>::type type;
};
template<class List>
struct tl_first_n<List, 0>
{
typedef type_list<> type;
};
// list last_n(size_t)
template<size_t TargetSize, size_t Size, class List, typename... T>
struct tl_last_n_impl;
template<size_t TargetSize, size_t Size, typename T0, typename... T>
struct tl_last_n_impl<TargetSize, Size, type_list<>, T0, T...>
{
typedef typename tl_last_n_impl<
TargetSize, Size-1,
type_list<>, T...
>::type
type;
};
template<size_t Size, typename... T>
struct tl_last_n_impl<Size, Size, type_list<>, T...>
{ {
typedef type_list<T...> type; static constexpr bool value =
Predicate<typename List::head>::value
&& tl_forall<typename List::tail, Predicate>::value;
}; };
template<size_t TargetSize, size_t Size, typename L0, typename... L, typename... T> template<template<typename> class Predicate>
struct tl_last_n_impl<TargetSize, Size, type_list<L0, L...>, T...> struct tl_forall<type_list<>, Predicate>
{ {
typedef typename tl_last_n_impl<TargetSize, Size, static constexpr bool value = true;
type_list<L...>, T..., L0>::type type;
}; };
/** template<class ListA, class ListB, template<typename, typename> class Predicate>
* @brief Creates a new list from the first @p N elements of @p List. struct tl_forall2_impl
*/
template<class List, size_t N>
struct tl_last_n
{ {
static_assert(List::size >= N, "List::size < N"); static constexpr bool value =
typedef typename tl_last_n_impl<N, List::size, List>::type type; Predicate<typename ListA::head, typename ListB::head>::value
&& tl_forall2_impl<
typename ListA::tail,
typename ListB::tail,
Predicate
>::value;
}; };
template<class List> template<template<typename, typename> class Predicate>
struct tl_last_n<List, 0> struct tl_forall2_impl<type_list<>, type_list<>, Predicate>
{ {
typedef type_list<> type; static constexpr bool value = true;
}; };
// bool forall(predicate)
/** /**
* @brief Tests whether a predicate holds for all elements of a list. * @brief Tests whether a binary predicate holds for all
* corresponding elements of @p ListA and @p ListB.
*/ */
template<class List, template<typename> class Predicate> template<class ListA, class ListB, template<typename, typename> class Predicate>
struct tl_forall struct tl_binary_forall
{ {
static constexpr bool value = static constexpr bool value =
Predicate<class List::head>::value ListA::size == ListB::size
&& tl_forall<class List::tail, Predicate>::value; && tl_forall2_impl<ListA, ListB, Predicate>::value;
};
template<template<typename> class Predicate>
struct tl_forall<type_list<>, Predicate>
{
static constexpr bool value = true;
}; };
/** /**
...@@ -677,7 +753,7 @@ struct tl_pad_right_impl; ...@@ -677,7 +753,7 @@ struct tl_pad_right_impl;
template<class List, size_t OldSize, size_t NewSize, typename FillType> template<class List, size_t OldSize, size_t NewSize, typename FillType>
struct tl_pad_right_impl<List, false, OldSize, NewSize, FillType> struct tl_pad_right_impl<List, false, OldSize, NewSize, FillType>
{ {
typedef typename tl_first_n<List, NewSize>::type type; typedef typename tl_slice<List, 0, NewSize>::type type;
}; };
template<class List, size_t Size, typename FillType> template<class List, size_t Size, typename FillType>
...@@ -703,7 +779,7 @@ struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType> ...@@ -703,7 +779,7 @@ struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType>
* @brief Resizes the list to contain @p NewSize elements and uses * @brief Resizes the list to contain @p NewSize elements and uses
* @p FillType to initialize the new elements with. * @p FillType to initialize the new elements with.
*/ */
template<class List, size_t NewSize, typename FillType> template<class List, size_t NewSize, typename FillType = void_type>
struct tl_pad_right struct tl_pad_right
{ {
typedef typename tl_pad_right_impl< typedef typename tl_pad_right_impl<
......
...@@ -90,11 +90,6 @@ struct invoke_policy_helper ...@@ -90,11 +90,6 @@ struct invoke_policy_helper
{ {
storage = *reinterpret_cast<T const*>(tup.at(i++)); storage = *reinterpret_cast<T const*>(tup.at(i++));
} }
//template<typename T>
//void operator()(ge_mutable_reference_wrapper<T>& storage)
//{
// storage = *reinterpret_cast<T*>(tup.mutable_at(i++));
//}
}; };
template<typename T> template<typename T>
...@@ -103,14 +98,26 @@ struct std_ref_wrapped ...@@ -103,14 +98,26 @@ struct std_ref_wrapped
typedef std::reference_wrapper<T> type; typedef std::reference_wrapper<T> type;
}; };
template<typename T>
struct std_ref_wrapped<T&>
{
typedef std::reference_wrapper<T> type;
};
template<typename T> template<typename T>
struct gref_wrapped struct gref_wrapped
{ {
typedef ge_reference_wrapper<T> type; typedef ge_reference_wrapper<typename util::rm_ref<T>::type> type;
}; };
template<typename T> template<typename T>
struct gref_mutable_wrapped struct gref_mutable_wrapped
{
typedef ge_mutable_reference_wrapper<const typename util::rm_ref<T>::type> type;
};
template<typename T>
struct gref_mutable_wrapped<T&>
{ {
typedef ge_mutable_reference_wrapper<T> type; typedef ge_mutable_reference_wrapper<T> type;
}; };
...@@ -131,44 +138,54 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern> ...@@ -131,44 +138,54 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern>
>::type >::type
arr_type; arr_type;
template<typename Target, typename... Ts> template<class Target, class Tup>
static bool _invoke_args(std::integral_constant<bool, true>, static inline bool shortcut(Target&, Tup&) { return false; }
Target& target, Ts&&... args)
template<class Target, typename... T>
static inline bool shortcut(Target& target,
detail::tdata<T...> const& tup,
typename util::enable_if<
util::tl_binary_forall<
util::type_list<T...>,
FilteredPattern,
std::is_convertible
>
>::type* = 0)
{ {
return target(std::forward<Ts>(args)...); util::unchecked_apply_tuple<bool>(target, tup);
} return true;
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, false>,
Target&, Ts&&...)
{
return false;
} }
template<typename Target, typename... Ts> template<class Target, typename... T>
static bool invoke_args(Target& target, Ts&&... args) static inline bool shortcut(Target& target,
detail::tdata<T...>& tup,
typename util::enable_if<
util::tl_binary_forall<
util::type_list<T...>,
FilteredPattern,
std::is_convertible
>
>::type* = 0)
{ {
typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming; //static_assert(false, "");
std::integral_constant<bool, std::is_same<incoming, Pattern>::value> util::unchecked_apply_tuple<bool>(target, tup);
token; return true;
return _invoke_args(token, target, std::forward<Ts>(args)...);
} }
template<class Target, typename NativeArg, typename Tuple> template<class Target, typename NativeArg, typename Tuple>
static bool invoke_tuple(Target& target, static bool invoke(Target& target,
std::type_info const& arg_types, std::type_info const& arg_types,
detail::tuple_impl_info timpl, detail::tuple_impl_info timpl,
NativeArg native_arg, NativeArg* native_arg,
Tuple& tup) Tuple& tup)
{ {
if (shortcut(target, tup)) return true;
if (arg_types == typeid(FilteredPattern)) if (arg_types == typeid(FilteredPattern))
{ {
if (native_arg) if (native_arg)
{ {
typedef typename util::if_else_c< typedef typename util::if_else_c<
std::is_const< std::is_const<NativeArg>::value,
typename std::remove_pointer<NativeArg>::type
>::value,
native_data_type const*, native_data_type const*,
util::wrapped<native_data_type*> util::wrapped<native_data_type*>
>::type >::type
...@@ -200,8 +217,6 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern> ...@@ -200,8 +217,6 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern>
} }
// either dynamically typed or statically typed but not a native tuple // either dynamically typed or statically typed but not a native tuple
// Tup::types is a type list with const qualified types if
// Tup represents 'encapsulated arguments'
typedef typename detail::tdata_from_type_list< typedef typename detail::tdata_from_type_list<
typename util::tl_map< typename util::tl_map<
typename util::if_else< typename util::if_else<
...@@ -240,8 +255,9 @@ struct deduce_tup_type<wildcard_position::trailing, Tuple, FilteredPattern> ...@@ -240,8 +255,9 @@ struct deduce_tup_type<wildcard_position::trailing, Tuple, FilteredPattern>
{ {
typedef typename detail::tdata_from_type_list< typedef typename detail::tdata_from_type_list<
typename util::tl_map< typename util::tl_map<
typename util::tl_first_n< typename util::tl_slice<
typename Tuple::types, typename Tuple::types,
0,
FilteredPattern::size FilteredPattern::size
>::type, >::type,
gref_mutable_wrapped gref_mutable_wrapped
...@@ -286,13 +302,12 @@ template<class Pattern, class FilteredPattern> ...@@ -286,13 +302,12 @@ template<class Pattern, class FilteredPattern>
struct invoke_policy_impl<wildcard_position::trailing, Pattern, FilteredPattern> struct invoke_policy_impl<wildcard_position::trailing, Pattern, FilteredPattern>
{ {
template<class Target, typename NativeArg, class Tuple> template<class Target, typename NativeArg, class Tuple>
static bool invoke_tuple(Target& target, static bool invoke(Target& target,
std::type_info const&, std::type_info const&,
detail::tuple_impl_info, detail::tuple_impl_info,
NativeArg, NativeArg,
Tuple& tup) Tuple& tup)
{ {
cout << __LINE__ << endl;
typedef typename detail::static_types_array_from_type_list< typedef typename detail::static_types_array_from_type_list<
FilteredPattern FilteredPattern
>::type >::type
...@@ -330,91 +345,11 @@ cout << __LINE__ << endl; ...@@ -330,91 +345,11 @@ cout << __LINE__ << endl;
template<class Pattern> template<class Pattern>
struct invoke_policy struct invoke_policy
: invoke_policy_impl<
get_wildcard_position<Pattern>(),
Pattern,
typename util::tl_filter_not_type<Pattern, anything>::type>
{ {
typedef typename util::tl_filter_not_type<Pattern, anything>::type
filtered_pattern;
static constexpr wildcard_position wc_pos =
get_wildcard_position<Pattern>();
typedef invoke_policy_impl<
get_wildcard_position<Pattern>(),
Pattern,
filtered_pattern>
impl;
typedef typename detail::tdata_from_type_list<
filtered_pattern
>::type
native_data_type;
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, false>,
Target&, Ts&&...)
{
return false;
}
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, true>,
Target& target, Ts&&... args)
{
detail::tdata<
std::reference_wrapper<
typename std::remove_reference<Ts>::type
>...
> wrapped_args{std::forward<Ts>(args)...};
auto const& arg_types =
typeid(util::type_list<typename util::rm_ref<Ts>::type...>);
return impl::invoke_tuple(target, arg_types,
detail::statically_typed,
static_cast<native_data_type*>(nullptr),
wrapped_args);
}
template<typename Target, typename... Ts>
static bool invoke_args(std::integral_constant<bool, false>,
Target& target, Ts&&... args)
{
std::integral_constant<bool, sizeof...(Ts) >= filtered_pattern::size> x;
return _invoke_args(x, target, std::forward<Ts>(args)...);
}
template<typename Target, typename... Ts>
static bool invoke_args(std::integral_constant<bool, true>,
Target& target, Ts&&... args)
{
return impl::invoke_args(target, std::forward<Ts>(args)...);
}
template<typename Target, typename... Ts>
static bool invoke(Target& target, Ts&&... args)
{
std::integral_constant<bool, wc_pos == wildcard_position::nil> token;
return invoke_args(token, target, std::forward<Ts>(args)...);
}
template<class Target>
static bool invoke(Target& target,
std::type_info const& arg0,
detail::tuple_impl_info arg1,
void const* arg2,
detail::abstract_tuple const& arg3)
{
return impl::invoke_tuple(target, arg0, arg1, arg2, arg3);
}
template<typename Target>
static bool invoke(Target& target,
std::type_info const& arg1,
detail::tuple_impl_info arg2,
void* arg3,
detail::abstract_tuple& arg4)
{
return impl::invoke_tuple(target, arg1, arg2, arg3, arg4);
}
}; };
template<class PartialFun> template<class PartialFun>
...@@ -440,6 +375,85 @@ struct add_const_ref ...@@ -440,6 +375,85 @@ struct add_const_ref
typedef T const& type; typedef T const& type;
}; };
template<bool IsInvokable, typename T>
struct pj_wrap_
{
typedef T type;
};
template<typename T>
struct pj_wrap_<true, T>
{
typedef typename util::get_callable_trait<T>::type ctrait;
typedef typename util::rm_option<typename ctrait::result_type>::type type;
};
template<typename T>
struct pj_wrap_<false, ge_mutable_reference_wrapper<T>&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct pj_wrap_<false, ge_mutable_reference_wrapper<T> const&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct pj_wrap_<false, T&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct pj_wrap
{
typedef typename pj_wrap_<util::is_callable<T>::value, T>::type type;
};
template<typename T>
struct result_inference
{
typedef typename util::rm_option<typename util::get_result_type<T>::type>::type type;
};
template<>
struct result_inference<util::void_type>
{
typedef util::void_type type;
};
template<typename T0, typename T1>
struct mutable_ref_inference
{
typedef T1 type;
};
template<typename T>
struct mutable_ref_inference<T&, T>
{
typedef T& type;
};
template<typename T>
struct wrap_ref
{
typedef T type;
};
template<typename T>
struct wrap_ref<ge_mutable_reference_wrapper<T>&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct wrap_ref<T&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
/** /**
* @brief Projection implemented by a set of functors. * @brief Projection implemented by a set of functors.
*/ */
...@@ -460,50 +474,47 @@ class projection ...@@ -460,50 +474,47 @@ class projection
pattern_type, pattern_type,
anything anything
>::type >::type
filtered_pattern_type; filtered_pattern;
static_assert(ProjectionFuns::size <= filtered_pattern_type::size, static_assert(ProjectionFuns::size <= filtered_pattern::size,
"invalid projection (too many functions)"); "invalid projection (too many functions)");
typedef TargetSignature arg_types; typedef typename util::tl_pad_left<
TargetSignature,
filtered_pattern::size
>::type
padded_signature;
// fill arg_types with first arguments of const-references typedef typename util::tl_zip<
// deduced from filtered_pattern_type
typedef typename util::tl_zipped_map<
typename util::tl_zip< typename util::tl_zip<
typename util::tl_pad_left< typename util::tl_pad_left<
arg_types, typename util::tl_map<
filtered_pattern_type::size, ProjectionFuns,
util::void_type result_inference
>::type,
filtered_pattern::size
>::type, >::type,
typename util::tl_map< padded_signature,
filtered_pattern_type, util::left_or_right
add_const_ref
>::type
>::type, >::type,
util::left_or_right typename util::tl_map<
filtered_pattern,
add_const_ref
>::type
>::type >::type
filled_arg_types; projected_arg_types;
// get a container that manages const and non-const references /*
typedef typename util::tl_zipped_map< typedef typename util::tl_zip<
typename util::tl_zip< padded_signature,
filled_arg_types, typename util::tl_map<
typename util::tl_pad_right< filtered_pattern,
ProjectionFuns, add_const_ref
filtered_pattern_type::size,
util::void_type
>::type
>::type, >::type,
cf_transformed_type util::left_or_right
>::type >::type
projection_map;
typedef typename util::tl_map<projection_map, cf_unwrap>::type
projected_arg_types; projected_arg_types;
*/
typedef typename detail::tdata_from_type_list<projection_map>::type
collected_arg_types;
projection(fun_container const& args) : m_funs(args) projection(fun_container const& args) : m_funs(args)
{ {
...@@ -511,87 +522,64 @@ class projection ...@@ -511,87 +522,64 @@ class projection
projection(projection const&) = default; projection(projection const&) = default;
template<class PartialFun, typename... Args>
bool _arg_impl(std::integral_constant<bool, true>,
PartialFun& fun, Args&&... args ) const
{
collected_arg_types pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...))
{
projection_helper<PartialFun> helper{fun};
return util::unchecked_apply_tuple<bool>(helper, pargs);
}
return false;
}
template<class PartialFun, typename... Args>
inline bool _arg_impl(std::integral_constant<bool, false>,
PartialFun&, Args&&... ) const
{
return false;
}
template<class PartialFun, typename... Args>
bool _arg_fwd(std::integral_constant<bool, false>,
PartialFun&, Args&&...) const
{
return false;
}
template<class PartialFun, typename... Args>
bool _arg_fwd(std::integral_constant<bool, true>,
PartialFun& fun, Args&&... args) const
{
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming;
std::integral_constant<
bool,
util::tl_zipped_forall<
typename util::tl_zip<incoming, filtered_pattern_type>::type,
std::is_convertible
>::value
> token;
return _arg_impl(token, fun, std::forward<Args>(args)...);
}
/** /**
* @brief Invokes @p fun with a projection of <tt>args...</tt>. * @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/ */
template<class PartialFun, typename... Args> template<class PartialFun, typename... Args>
bool operator()(PartialFun& fun, Args&&... args) const bool operator()(PartialFun& fun, Args&&... args) const
{ {
std::integral_constant< static constexpr bool can_collect =
bool, util::tl_binary_forall<
sizeof...(Args) == filtered_pattern_type::size util::type_list<Args...>,
> token; typename util::tl_zip<
return _arg_fwd(token, fun, std::forward<Args>(args)...); padded_signature,
filtered_pattern,
mutable_ref_inference
>::type,
std::is_convertible
>::value;
std::integral_constant<bool, can_collect> token;
return invoke(token, fun, std::forward<Args>(args)...);
} }
private: private:
template<typename Storage, typename T> template<class PartialFun, typename... Args>
static inline bool fetch_(Storage& storage, T& value) bool invoke(std::integral_constant<bool, false>,
{ PartialFun&, Args&&... ) const
storage = value;
return true;
}
template<typename T>
static inline bool fetch_(T&, T const&)
{ {
return false; return false;
} }
template<typename T> template<class PartialFun, typename... Args>
static inline bool fetch_(ge_mutable_reference_wrapper<T>&, bool invoke(std::integral_constant<bool, true>,
ge_mutable_reference_wrapper<const T>&) PartialFun&, Args&&... ) const
{ {
/*
typedef typename util::tl_map<
projected_arg_types,
wrap_ref
>::type
collected_arg_types;
//typedef projected_arg_types collected_arg_types;
typename detail::tdata_from_type_list<collected_arg_types>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...))
{
projection_helper<PartialFun> helper{fun};
return util::unchecked_apply_tuple<bool>(helper, pargs);
}
*/
return false; return false;
} }
template<typename T> template<typename Storage, typename T>
static inline bool fetch_(ge_mutable_reference_wrapper<T>&, T const&) static inline bool fetch_(Storage& storage, T&& value)
{ {
return false; storage = std::forward<T>(value);
return true;
} }
template<class Storage> template<class Storage>
...@@ -612,12 +600,9 @@ class projection ...@@ -612,12 +600,9 @@ class projection
} }
template<typename Storage, typename T> template<typename Storage, typename T>
static inline bool fetch(Storage& storage, static inline bool fetch(Storage& storage, util::void_type const&, T&& arg)
util::void_type const&,
T&& value)
{ {
storage = std::forward<T>(value); return fetch_(storage, std::forward<T>(arg));
return true;
} }
static inline bool collect(detail::tdata<>&, detail::tdata<> const&) static inline bool collect(detail::tdata<>&, detail::tdata<> const&)
...@@ -625,16 +610,6 @@ class projection ...@@ -625,16 +610,6 @@ class projection
return true; return true;
} }
template<class TData, typename T0, typename... Ts>
static inline bool collect(TData& td, detail::tdata<> const& tr,
T0&& arg0, Ts&&... args)
{
return fetch_(td.head, std::forward<T0>(arg0))
&& collect(td.tail(), tr.tail(), std::forward<Ts>(args)...);
//td.set(std::forward<T0>(arg0), std::forward<Ts>(args)...);
return true;
}
template<class TData, class Trans, typename T0, typename... Ts> template<class TData, class Trans, typename T0, typename... Ts>
static inline bool collect(TData& td, Trans const& tr, static inline bool collect(TData& td, Trans const& tr,
T0&& arg0, Ts&&... args) T0&& arg0, Ts&&... args)
...@@ -645,37 +620,6 @@ class projection ...@@ -645,37 +620,6 @@ class projection
}; };
/*
template<class Pattern, class TargetSignature>
class projection<Pattern, TargetSignature, util::type_list<> >
{
public:
typedef Pattern pattern_type;
typedef typename util::tl_filter_not_type<
pattern_type,
anything
>::type
filtered_pattern_type;
typedef filtered_pattern_type projected_arg_types;
projection(detail::tdata<>) { }
projection(projection&&) = default;
projection(projection const&) = default;
template<class PartialFun, typename... Args>
bool operator()(PartialFun& fun, Args&&... args) const
{
projection_helper<PartialFun> helper{fun};
return helper(std::forward<Args>(args)...);
}
};
*/
template<class Expr, class Guard, class Transformers, class Pattern> template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl struct get_cfl
{ {
...@@ -731,6 +675,7 @@ struct invoke_helper2 ...@@ -731,6 +675,7 @@ struct invoke_helper2
template<typename... Args> template<typename... Args>
bool operator()(Args&&... args) const bool operator()(Args&&... args) const
{ {
//static_assert(false, "foo");
Token token; Token token;
invoke_helper3<Data> fun{data}; invoke_helper3<Data> fun{data};
return util::static_foreach<0, Token::size>::eval_or(token, fun, std::forward<Args>(args)...); return util::static_foreach<0, Token::size>::eval_or(token, fun, std::forward<Args>(args)...);
...@@ -788,51 +733,6 @@ struct is_manipulator_leaf<std::pair<First, Second> > ...@@ -788,51 +733,6 @@ struct is_manipulator_leaf<std::pair<First, Second> >
static constexpr bool value = Second::manipulates_args; static constexpr bool value = Second::manipulates_args;
}; };
template<bool ManipulatesArgs, class EvalOrder>
struct pjf_invoke
{
template<typename Leaves>
static bool _(Leaves const& leaves, any_tuple const& tup)
{
EvalOrder token;
invoke_helper<decltype(leaves)> fun{leaves};
auto const& cvals = *(tup.cvals());
return util::static_foreach<0, EvalOrder::size>
::eval_or(token,
fun,
*(cvals.type_token()),
cvals.impl_type(),
cvals.native_data(),
cvals);
}
};
template<class EvalOrder>
struct pjf_invoke<true, EvalOrder>
{
template<typename Leaves>
static bool _(Leaves const& leaves, any_tuple& tup)
{
EvalOrder token;
invoke_helper<decltype(leaves)> fun{leaves};
tup.force_detach();
auto& vals = *(tup.vals());
return util::static_foreach<0, EvalOrder::size>
::eval_or(token,
fun,
*(vals.type_token()),
vals.impl_type(),
vals.mutable_native_data(),
vals);
}
template<typename Leaves>
static bool _(Leaves const& leaves, any_tuple const& tup)
{
any_tuple tup_copy{tup};
return _(leaves, tup_copy);
}
};
void collect_tdata(detail::tdata<>&) void collect_tdata(detail::tdata<>&)
{ {
} }
...@@ -850,6 +750,37 @@ void collect_tdata(Storage& storage, Arg0 const& arg0, Args const&... args) ...@@ -850,6 +750,37 @@ void collect_tdata(Storage& storage, Arg0 const& arg0, Args const&... args)
collect_tdata(storage.tail(), arg0.tail(), args...); collect_tdata(storage.tail(), arg0.tail(), args...);
} }
template<bool IsManipulator, typename T0, typename T1>
struct pj_fwd_
{
typedef T1 type;
};
template<bool IsManipulator, typename T>
struct pj_fwd_<IsManipulator, T const&, T>
{
typedef std::reference_wrapper<const T> type;
};
template<typename T>
struct pj_fwd_<true, T&, T>
{
typedef std::reference_wrapper<T> type;
};
template<bool IsManipulator, typename T>
struct pj_fwd
{
typedef typename pj_fwd_<
IsManipulator,
T,
typename detail::implicit_conversions<
typename util::rm_ref<T>::type
>::type
>::type
type;
};
/** /**
* @brief A function that works on the projection of given data rather than * @brief A function that works on the projection of given data rather than
* on the data itself. * on the data itself.
...@@ -879,16 +810,47 @@ class projected_fun ...@@ -879,16 +810,47 @@ class projected_fun
projected_fun(projected_fun const&) = default; projected_fun(projected_fun const&) = default;
bool _invoke(any_tuple const& tup) const
{
eval_order token;
invoke_helper<decltype(m_leaves)> fun{m_leaves};
auto& cvals = *(tup.cvals());
return util::static_foreach<0, eval_order::size>
::eval_or(token,
fun,
*(cvals.type_token()),
cvals.impl_type(),
cvals.native_data(),
cvals);
}
bool _invoke(any_tuple& tup) const
{
eval_order token;
invoke_helper<decltype(m_leaves)> fun{m_leaves};
tup.force_detach();
auto& vals = *(tup.vals());
return util::static_foreach<0, eval_order::size>
::eval_or(token,
fun,
*(vals.type_token()),
vals.impl_type(),
vals.mutable_native_data(),
vals);
}
bool invoke(any_tuple const& tup) const bool invoke(any_tuple const& tup) const
{ {
return pjf_invoke<has_manipulator, eval_order> if (has_manipulator)
::_(m_leaves, tup); return invoke(any_tuple{tup});
return _invoke(tup);
} }
bool invoke(any_tuple& tup) const bool invoke(any_tuple& tup) const
{ {
return pjf_invoke<has_manipulator, eval_order> if (!has_manipulator)
::_(m_leaves, tup); return _invoke(static_cast<any_tuple const&>(tup));
return _invoke(tup);
} }
bool invoke(any_tuple&& tup) const bool invoke(any_tuple&& tup) const
...@@ -898,19 +860,36 @@ class projected_fun ...@@ -898,19 +860,36 @@ class projected_fun
} }
template<typename... Args> template<typename... Args>
bool invoke_args(Args&&... args) const bool operator()(Args&&... args) const
{ {
typedef detail::tdata<typename pj_fwd<has_manipulator, Args>::type...>
tuple_type;
// applies implicit conversions etc
tuple_type tup{std::forward<Args>(args)...};
typedef typename util::if_else_c<
has_manipulator,
tuple_type&,
util::wrapped<tuple_type const&>
>::type
ref_type;
typedef typename util::if_else_c<
has_manipulator,
void*,
util::wrapped<void const*>
>::type
ptr_type;
eval_order token; eval_order token;
invoke_helper<decltype(m_leaves)> fun{m_leaves}; invoke_helper<decltype(m_leaves)> fun{m_leaves};
return util::static_foreach<0, eval_order::size> return util::static_foreach<0, eval_order::size>
::eval_or(token, fun, std::forward<Args>(args)...); ::eval_or(token,
} fun,
typeid(util::type_list<typename util::rm_ref<Args>::type...>),
template<typename... Args> detail::statically_typed,
bool operator()(Args&&... args) const static_cast<ptr_type>(nullptr),
{ static_cast<ref_type>(tup));
// applies implicit conversions and passes rvalues as const lvalue refs
return invoke_args(pjf_fwd<Args>::_(args)...);
} }
template<class... Rhs> template<class... Rhs>
...@@ -1270,6 +1249,7 @@ size_t test__tuple() ...@@ -1270,6 +1249,7 @@ size_t test__tuple()
{ {
CPPA_TEST(test__tuple); CPPA_TEST(test__tuple);
/*
using namespace cppa::placeholders; using namespace cppa::placeholders;
typedef typename util::tl_group_by<zz0, std::is_same>::type zz1; typedef typename util::tl_group_by<zz0, std::is_same>::type zz1;
...@@ -1410,7 +1390,9 @@ size_t test__tuple() ...@@ -1410,7 +1390,9 @@ size_t test__tuple()
CPPA_CHECK(f11("10")); CPPA_CHECK(f11("10"));
CPPA_CHECK_EQUAL(10, f11_fun); CPPA_CHECK_EQUAL(10, f11_fun);
//exit(0); exit(0);
*/
/* /*
VERBOSE(f00(42, 42)); VERBOSE(f00(42, 42));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment