Commit cc1c3445 authored by neverlord's avatar neverlord

pattern matching

parent 05b61ecf
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define TDATA_HPP #define TDATA_HPP
#include <typeinfo> #include <typeinfo>
#include <functional>
#include "cppa/get.hpp" #include "cppa/get.hpp"
#include "cppa/option.hpp" #include "cppa/option.hpp"
...@@ -44,6 +45,7 @@ ...@@ -44,6 +45,7 @@
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/boxed.hpp" #include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp" #include "cppa/detail/implicit_conversions.hpp"
...@@ -66,6 +68,36 @@ inline void* ptr_to(T* what) { return what; } ...@@ -66,6 +68,36 @@ inline void* ptr_to(T* what) { return what; }
template<typename T> template<typename T>
inline void const* ptr_to(T const* what) { return what; } inline void const* ptr_to(T const* what) { return what; }
template<typename T>
inline void* ptr_to(std::reference_wrapper<T> const& what)
{
return &(what.get());
}
template<typename T>
inline void const* ptr_to(std::reference_wrapper<const T> const& what)
{
return &(what.get());
}
template<typename T>
inline uniform_type_info const* utype_of(T const&)
{
return static_types_array<T>::arr[0];
}
template<typename T>
inline uniform_type_info const* utype_of(std::reference_wrapper<T> const&)
{
return static_types_array<typename util::rm_ref<T>::type>::arr[0];
}
template<typename T>
inline uniform_type_info const* utype_of(T const* ptr)
{
return utype_of(*ptr);
}
template<typename T> template<typename T>
struct boxed_or_void struct boxed_or_void
{ {
...@@ -78,8 +110,20 @@ struct boxed_or_void<util::void_type> ...@@ -78,8 +110,20 @@ struct boxed_or_void<util::void_type>
static constexpr bool value = true; static constexpr bool value = true;
}; };
template<typename T>
struct unbox_ref
{
typedef T type;
};
template<typename T>
struct unbox_ref<std::reference_wrapper<T> >
{
typedef T type;
};
/* /*
* "enhanced std::tuple" * "enhanced" std::tuple
*/ */
template<typename...> template<typename...>
struct tdata; struct tdata;
...@@ -112,21 +156,27 @@ struct tdata<> ...@@ -112,21 +156,27 @@ struct tdata<>
inline tdata(tdata&&) { } inline tdata(tdata&&) { }
inline tdata(tdata const&) { } inline tdata(tdata const&) { }
//// swallow "arg_match" silently inline size_t size() const { return num_elements; }
//constexpr tdata(util::wrapped<util::arg_match_t> const&) { }
tdata<>& tail() { return *this; } tdata<>& tail() { return *this; }
tdata<> const& tail() const { return *this; } tdata<> const& tail() const { return *this; }
tdata<> const& ctail() const { return *this; }
inline void const* at(size_t) const inline void const* at(size_t) const
{ {
throw std::out_of_range(""); throw std::out_of_range("tdata<>");
}
inline void* mutable_at(size_t)
{
throw std::out_of_range("tdata<>");
} }
inline uniform_type_info const* type_at(size_t) const inline uniform_type_info const* type_at(size_t) const
{ {
throw std::out_of_range(""); throw std::out_of_range("tdata<>");
} }
inline void set() { } inline void set() { }
...@@ -187,7 +237,10 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -187,7 +237,10 @@ struct tdata<Head, Tail...> : tdata<Tail...>
typedef tdata<Tail...> super; typedef tdata<Tail...> super;
typedef util::type_list<Head, Tail...> types; typedef util::type_list<
typename unbox_ref<Head>::type,
typename unbox_ref<Tail>::type...>
types;
Head head; Head head;
...@@ -216,16 +269,7 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -216,16 +269,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
tdata(tdata const&) = default; tdata(tdata const&) = default;
// allow partial initialization
//template<typename... Args>
//tdata(Head const& v0, Args const&... vals) : super(vals...), head(v0) { }
// allow partial initialization
//template<typename... Args>
//tdata(Head&& v0, Args const&... vals) : super(vals...), head(std::move(v0)) { }
// allow (partial) initialization from a different tdata // allow (partial) initialization from a different tdata
// with traling extra arguments to initialize additional arguments
template<typename... Y> template<typename... Y>
tdata(tdata<Y...>& other) : super(other.tail()), head(other.head) tdata(tdata<Y...>& other) : super(other.tail()), head(other.head)
...@@ -243,42 +287,6 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -243,42 +287,6 @@ struct tdata<Head, Tail...> : tdata<Tail...>
{ {
} }
/*
template<typename... Y>
tdata(Head const& arg, tdata<Y...> const& other)
: super(other), head(arg)
{
}
template<typename... Y>
tdata(tdata<Head> const& arg, tdata<Y...> const& other)
: super(other), head(arg.head)
{
}
template<typename ExtraArg, typename Y0, typename Y1, typename... Y>
tdata(tdata<Y0, Y1, Y...> const& other, ExtraArg const& arg)
: super(other.tail(), arg), head(other.head)
{
}
template<typename ExtraArg, typename Y0>
tdata(tdata<Y0> const& other, ExtraArg const& arg,
typename util::enable_if_c< std::is_same<ExtraArg, ExtraArg>::value
&& (sizeof...(Tail) > 0)>::type* = 0)
: super(arg), head(other.head)
{
}
template<typename ExtraArg, typename Y0>
tdata(tdata<Y0> const& other, ExtraArg const& arg,
typename util::enable_if_c< std::is_same<ExtraArg, ExtraArg>::value
&& (sizeof...(Tail) == 0)>::type* = 0)
: super(), head(other.head, arg)
{
}
*/
template<typename... Y> template<typename... Y>
tdata& operator=(tdata<Y...> const& other) tdata& operator=(tdata<Y...> const& other)
{ {
...@@ -293,20 +301,39 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -293,20 +301,39 @@ struct tdata<Head, Tail...> : tdata<Tail...>
super::set(std::forward<Args>(args)...); super::set(std::forward<Args>(args)...);
} }
inline size_t size() const { return num_elements; }
// upcast // upcast
inline tdata<Tail...>& tail() { return *this; } inline tdata<Tail...>& tail() { return *this; }
inline tdata<Tail...> const& tail() const { return *this; } inline tdata<Tail...> const& tail() const { return *this; }
inline tdata<Tail...> const& ctail() const { return *this; }
inline void const* at(size_t p) const inline void const* at(size_t p) const
{ {
return (p == 0) ? ptr_to(head) : super::at(p-1); return (p == 0) ? ptr_to(head) : super::at(p - 1);
} }
inline uniform_type_info const* type_at(size_t p) const inline void* mutable_at(size_t p)
{ {
return (p == 0) ? uniform_typeid(typeid(Head)) : super::type_at(p-1); if (p == 0)
{
# ifdef CPPA_DEBUG
if (std::is_same<decltype(ptr_to(head)), void const*>::value)
{
throw std::logic_error{"mutable_at with const head"};
}
# endif
return const_cast<void*>(ptr_to(head));
}
return super::mutable_at(p - 1);
} }
inline uniform_type_info const* type_at(size_t p) const
{
return (p == 0) ? utype_of(head) : super::type_at(p-1);
}
Head& _back(std::integral_constant<size_t, 0>) Head& _back(std::integral_constant<size_t, 0>)
{ {
......
...@@ -108,7 +108,7 @@ class tuple_view : public abstract_tuple ...@@ -108,7 +108,7 @@ class tuple_view : public abstract_tuple
void* mutable_at(size_t pos) void* mutable_at(size_t pos)
{ {
CPPA_REQUIRE(pos < size()); CPPA_REQUIRE(pos < size());
return const_cast<void*>(at(pos)); return m_data.mutable_at(pos);
} }
uniform_type_info const* type_at(size_t pos) const uniform_type_info const* type_at(size_t pos) const
......
...@@ -322,12 +322,16 @@ struct ge_mutable_reference_wrapper ...@@ -322,12 +322,16 @@ struct ge_mutable_reference_wrapper
T* value; T* value;
ge_mutable_reference_wrapper() : value(nullptr) { } ge_mutable_reference_wrapper() : value(nullptr) { }
ge_mutable_reference_wrapper(T&&) = delete; ge_mutable_reference_wrapper(T&&) = delete;
ge_mutable_reference_wrapper(T const&) = delete;
ge_mutable_reference_wrapper(T& vref) : value(&vref) { } ge_mutable_reference_wrapper(T& vref) : value(&vref) { }
ge_mutable_reference_wrapper(ge_mutable_reference_wrapper const&) = default; ge_mutable_reference_wrapper(ge_mutable_reference_wrapper const&) = default;
ge_mutable_reference_wrapper& operator=(T& vref)
{
value = &vref;
return *this;
}
ge_mutable_reference_wrapper& operator=(ge_mutable_reference_wrapper const&) = default; ge_mutable_reference_wrapper& operator=(ge_mutable_reference_wrapper const&) = default;
T& get() { CPPA_REQUIRE(value != 0); return *value; } T& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T& () { CPPA_REQUIRE(value != 0); return *value; } operator T& () const { CPPA_REQUIRE(value != 0); return *value; }
}; };
template<typename T> template<typename T>
...@@ -338,6 +342,11 @@ struct ge_reference_wrapper ...@@ -338,6 +342,11 @@ struct ge_reference_wrapper
ge_reference_wrapper() : value(nullptr) { } ge_reference_wrapper() : value(nullptr) { }
ge_reference_wrapper(T const& val_ref) : value(&val_ref) { } ge_reference_wrapper(T const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default; ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(T const& vref)
{
value = &vref;
return *this;
}
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default; ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
T const& get() const { CPPA_REQUIRE(value != 0); return *value; } T const& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T const& () const { CPPA_REQUIRE(value != 0); return *value; } operator T const& () const { CPPA_REQUIRE(value != 0); return *value; }
...@@ -352,9 +361,9 @@ struct ge_reference_wrapper<bool> ...@@ -352,9 +361,9 @@ struct ge_reference_wrapper<bool>
ge_reference_wrapper(bool const& val_ref) : value(&val_ref) { } ge_reference_wrapper(bool const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default; ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default; ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
bool get() const { return *value; } bool get() const { CPPA_REQUIRE(value != 0); return *value; }
operator bool () const { return *value; } operator bool () const { CPPA_REQUIRE(value != 0); return *value; }
bool operator()() const { return *value; } bool operator()() const { CPPA_REQUIRE(value != 0); return *value; }
}; };
/** /**
......
...@@ -53,6 +53,16 @@ struct static_foreach_impl ...@@ -53,6 +53,16 @@ struct static_foreach_impl
::_ref(c, f, std::forward<Args>(args)...); ::_ref(c, f, std::forward<Args>(args)...);
} }
template<typename Container, typename Fun, typename... Args> template<typename Container, typename Fun, typename... Args>
static inline void _auto(Container& c, Fun& f, Args&&... args)
{
_ref(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline void _auto(Container const& c, Fun& f, Args&&... args)
{
_(c, f, std::forward<Args>(args)...);
}
template<typename Container, typename Fun, typename... Args>
static inline bool eval(Container const& c, Fun& f, Args&&... args) static inline bool eval(Container const& c, Fun& f, Args&&... args)
{ {
return f(get<Begin>(c), std::forward<Args>(args)...) return f(get<Begin>(c), std::forward<Args>(args)...)
...@@ -76,6 +86,8 @@ struct static_foreach_impl<false, X, Y> ...@@ -76,6 +86,8 @@ struct static_foreach_impl<false, X, Y>
template<typename... Args> template<typename... Args>
static inline void _ref(Args&&...) { } static inline void _ref(Args&&...) { }
template<typename... Args> template<typename... Args>
static inline void _auto(Args&&...) { }
template<typename... Args>
static inline bool eval(Args&&...) { return true; } static inline bool eval(Args&&...) { return true; }
template<typename... Args> template<typename... Args>
static inline bool eval_or(Args&&...) { return false; } static inline bool eval_or(Args&&...) { return false; }
......
...@@ -243,7 +243,15 @@ struct tl_find_if ...@@ -243,7 +243,15 @@ struct tl_find_if
// list first_n(size_t) // list first_n(size_t)
template<size_t N, class List, typename... T> template<size_t N, class List, typename... T>
struct tl_first_n_impl; 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> template<class List, typename... T>
struct tl_first_n_impl<0, List, T...> struct tl_first_n_impl<0, List, T...>
...@@ -251,12 +259,6 @@ struct tl_first_n_impl<0, List, T...> ...@@ -251,12 +259,6 @@ struct tl_first_n_impl<0, List, T...>
typedef type_list<T...> type; typedef type_list<T...> type;
}; };
template<size_t N, typename L0, typename... L, typename... T>
struct tl_first_n_impl<N, type_list<L0, L...>, T...>
{
typedef typename tl_first_n_impl<N-1, type_list<L...>, T..., L0>::type type;
};
/** /**
* @brief Creates a new list from the first @p N elements of @p List. * @brief Creates a new list from the first @p N elements of @p List.
*/ */
......
...@@ -81,15 +81,26 @@ struct invoke_policy_helper ...@@ -81,15 +81,26 @@ struct invoke_policy_helper
AbstractTuple& tup; AbstractTuple& tup;
invoke_policy_helper(AbstractTuple& tp) : i(0), tup(tp) { } invoke_policy_helper(AbstractTuple& tp) : i(0), tup(tp) { }
template<typename T> template<typename T>
void operator()(ge_reference_wrapper<T>& storage) void operator()(ge_mutable_reference_wrapper<T>& storage)
{ {
storage = *reinterpret_cast<T const*>(tup.at(i++)); storage = *reinterpret_cast<T*>(tup.mutable_at(i++));
} }
template<typename T> template<typename T>
void operator()(ge_mutable_reference_wrapper<T>& storage) void operator()(ge_mutable_reference_wrapper<const T>& storage)
{ {
storage = *reinterpret_cast<T*>(tup.mutable_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>
struct std_ref_wrapped
{
typedef std::reference_wrapper<T> type;
}; };
template<typename T> template<typename T>
...@@ -104,23 +115,21 @@ struct gref_mutable_wrapped ...@@ -104,23 +115,21 @@ struct gref_mutable_wrapped
typedef ge_mutable_reference_wrapper<T> type; typedef ge_mutable_reference_wrapper<T> type;
}; };
template<class NativeData, class WrappedRefs, class WrappedRefsForwarding> template<wildcard_position, class Pattern, class FilteredPattern>
struct invoke_policy_token struct invoke_policy_impl;
{
typedef NativeData native_type;
typedef WrappedRefs wrapped_refs;
typedef WrappedRefsForwarding wrapped_refs_fwd;
};
template<wildcard_position, class Pattern>
struct invoke_policy;
template<class Pattern> template<class Pattern, class FilteredPattern>
struct invoke_policy<wildcard_position::nil, Pattern> struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern>
{ {
typedef Pattern filtered_pattern; typedef typename detail::tdata_from_type_list<
typedef typename detail::tdata_from_type_list<Pattern>::type native_data_type; FilteredPattern
typedef typename detail::static_types_array_from_type_list<Pattern>::type arr_type; >::type
native_data_type;
typedef typename detail::static_types_array_from_type_list<
FilteredPattern
>::type
arr_type;
template<typename Target, typename... Ts> template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, true>, static bool _invoke_args(std::integral_constant<bool, true>,
...@@ -128,14 +137,16 @@ struct invoke_policy<wildcard_position::nil, Pattern> ...@@ -128,14 +137,16 @@ struct invoke_policy<wildcard_position::nil, Pattern>
{ {
return target(std::forward<Ts>(args)...); return target(std::forward<Ts>(args)...);
} }
template<typename Target, typename... Ts> template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, false>, static bool _invoke_args(std::integral_constant<bool, false>,
Target&, Ts&&...) Target&, Ts&&...)
{ {
return false; return false;
} }
template<typename Target, typename... Ts> template<typename Target, typename... Ts>
static bool invoke(Target& target, Ts&&... args) static bool invoke_args(Target& target, Ts&&... args)
{ {
typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming; typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming;
std::integral_constant<bool, std::is_same<incoming, Pattern>::value> std::integral_constant<bool, std::is_same<incoming, Pattern>::value>
...@@ -143,19 +154,26 @@ struct invoke_policy<wildcard_position::nil, Pattern> ...@@ -143,19 +154,26 @@ struct invoke_policy<wildcard_position::nil, Pattern>
return _invoke_args(token, target, std::forward<Ts>(args)...); return _invoke_args(token, target, std::forward<Ts>(args)...);
} }
template<class PolicyToken, class Target, typename NativeArg, typename AbstractTuple> template<class Target, typename NativeArg, typename Tuple>
static bool _invoke_tuple(PolicyToken, static bool invoke_tuple(Target& target,
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,
AbstractTuple& tup) Tuple& tup)
{ {
if (arg_types == typeid(filtered_pattern)) if (arg_types == typeid(FilteredPattern))
{ {
if (native_arg) if (native_arg)
{ {
auto arg = reinterpret_cast<typename PolicyToken::native_type>(native_arg); typedef typename util::if_else_c<
std::is_const<
typename std::remove_pointer<NativeArg>::type
>::value,
native_data_type const*,
util::wrapped<native_data_type*>
>::type
cast_type;
auto arg = reinterpret_cast<cast_type>(native_arg);
return util::unchecked_apply_tuple<bool>(target, *arg); return util::unchecked_apply_tuple<bool>(target, *arg);
} }
// 'fall through' // 'fall through'
...@@ -163,11 +181,11 @@ struct invoke_policy<wildcard_position::nil, Pattern> ...@@ -163,11 +181,11 @@ struct invoke_policy<wildcard_position::nil, Pattern>
else if (timpl == detail::dynamically_typed) else if (timpl == detail::dynamically_typed)
{ {
auto& arr = arr_type::arr; auto& arr = arr_type::arr;
if (tup.size() != filtered_pattern::size) if (tup.size() != FilteredPattern::size)
{ {
return false; return false;
} }
for (size_t i = 0; i < filtered_pattern::size; ++i) for (size_t i = 0; i < FilteredPattern::size; ++i)
{ {
if (arr[i] != tup.type_at(i)) if (arr[i] != tup.type_at(i))
{ {
...@@ -180,52 +198,222 @@ struct invoke_policy<wildcard_position::nil, Pattern> ...@@ -180,52 +198,222 @@ struct invoke_policy<wildcard_position::nil, Pattern>
{ {
return false; return false;
} }
// either dynamically typed or statically typed but not a native tuple // either dynamically typed or statically typed but not a native tuple
typename PolicyToken::wrapped_refs ttup; // Tup::types is a type list with const qualified types if
invoke_policy_helper<AbstractTuple> iph{tup}; // Tup represents 'encapsulated arguments'
util::static_foreach<0, filtered_pattern::size>::_ref(ttup, iph); typedef typename detail::tdata_from_type_list<
typename util::tl_map<
typename util::if_else<
std::is_const<Tuple>,
typename util::tl_map<Pattern, std::add_const>::type,
util::wrapped<Pattern>
>::type,
gref_mutable_wrapped
>::type
>::type
ttup_type;
ttup_type ttup;
typedef typename util::if_else<
std::is_const<Tuple>,
ttup_type const&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
//typename PolicyToken::wrapped_refs ttup;
invoke_policy_helper<Tuple> helper{tup};
util::static_foreach<0, FilteredPattern::size>::_ref(ttup, helper);
//return util::apply_tuple(target, ttup); //return util::apply_tuple(target, ttup);
typename PolicyToken::wrapped_refs_fwd ttup_fwd = ttup; ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd); return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
} }
};
template<class Target> template<wildcard_position, class Tuple, class FilteredPattern>
static bool invoke(Target& target, struct deduce_tup_type;
std::type_info const& arg_types,
detail::tuple_impl_info timpl, template<class Tuple, class FilteredPattern>
void const* native_arg, struct deduce_tup_type<wildcard_position::trailing, Tuple, FilteredPattern>
detail::abstract_tuple const& tup) {
{
typedef typename detail::tdata_from_type_list< typedef typename detail::tdata_from_type_list<
typename util::tl_map< typename util::tl_map<
filtered_pattern, typename util::tl_first_n<
gref_wrapped typename Tuple::types,
FilteredPattern::size
>::type,
gref_mutable_wrapped
>::type >::type
>::type >::type
wrapped_refs; type;
invoke_policy_token<native_data_type const*, typedef typename util::if_else<
wrapped_refs, std::is_const<Tuple>,
wrapped_refs const& > token; type const&,
return _invoke_tuple(token, target, arg_types, timpl, native_arg, tup); util::wrapped<type&>
} >::type
template<typename Target> ref_type;
static bool invoke(Target& target, };
std::type_info const& arg_types,
detail::tuple_impl_info timpl, template<class FilteredPattern>
void* native_arg, struct deduce_tup_type<wildcard_position::trailing, detail::abstract_tuple, FilteredPattern>
detail::abstract_tuple& tup) {
{
typedef typename detail::tdata_from_type_list< typedef typename detail::tdata_from_type_list<
typename util::tl_map< typename util::tl_map<
filtered_pattern, FilteredPattern,
gref_mutable_wrapped gref_mutable_wrapped
>::type >::type
>::type >::type
wrapped_refs; type;
invoke_policy_token<native_data_type*, typedef type& ref_type;
wrapped_refs, };
wrapped_refs& > token;
return _invoke_tuple(token, target, arg_types, timpl, native_arg, tup); template<class FilteredPattern>
struct deduce_tup_type<wildcard_position::trailing, const detail::abstract_tuple, FilteredPattern>
{
typedef typename detail::tdata_from_type_list<
typename util::tl_map<
FilteredPattern,
gref_wrapped
>::type
>::type
type;
typedef type const& ref_type;
};
template<class Pattern, class FilteredPattern>
struct invoke_policy_impl<wildcard_position::trailing, Pattern, FilteredPattern>
{
template<class Target, typename NativeArg, class Tuple>
static bool invoke_tuple(Target& target,
std::type_info const&,
detail::tuple_impl_info,
NativeArg,
Tuple& tup)
{
cout << __LINE__ << endl;
typedef typename detail::static_types_array_from_type_list<
FilteredPattern
>::type
arr_type;
auto& arr = arr_type::arr;
if (tup.size() < FilteredPattern::size)
{
return false;
}
for (size_t i = 0; i < FilteredPattern::size; ++i)
{
if (arr[i] != tup.type_at(i))
{
return false;
}
}
typedef deduce_tup_type<
wildcard_position::trailing,
Tuple,
FilteredPattern>
deduced;
typename deduced::type ttup;
invoke_policy_helper<Tuple> helper{tup};
util::static_foreach<0, FilteredPattern::size>::_ref(ttup, helper);
//return util::apply_tuple(target, ttup);
typename deduced::ref_type ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
return false;
}
};
template<class Pattern>
struct invoke_policy
{
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);
} }
}; };
...@@ -343,29 +531,69 @@ class projection ...@@ -343,29 +531,69 @@ class projection
return false; 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
{ {
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming;
std::integral_constant< std::integral_constant<
bool, bool,
std::is_same<filtered_pattern_type, incoming>::value sizeof...(Args) == filtered_pattern_type::size
> token; > token;
return _arg_impl(token, fun, std::forward<Args>(args)...); return _arg_fwd(token, fun, std::forward<Args>(args)...);
} }
private: private:
template<class Storage, typename T> template<typename Storage, typename T>
static inline bool fetch_(Storage& storage, T&& value) static inline bool fetch_(Storage& storage, T& value)
{ {
storage = std::forward<T>(value); storage = value;
return true; return true;
} }
template<typename T>
static inline bool fetch_(T&, T const&)
{
return false;
}
template<typename T>
static inline bool fetch_(ge_mutable_reference_wrapper<T>&,
ge_mutable_reference_wrapper<const T>&)
{
return false;
}
template<typename T>
static inline bool fetch_(ge_mutable_reference_wrapper<T>&, T const&)
{
return false;
}
template<class Storage> template<class Storage>
static inline bool fetch_(Storage& storage, option<Storage>&& value) static inline bool fetch_(Storage& storage, option<Storage>&& value)
{ {
...@@ -398,10 +626,12 @@ class projection ...@@ -398,10 +626,12 @@ class projection
} }
template<class TData, typename T0, typename... Ts> template<class TData, typename T0, typename... Ts>
static inline bool collect(TData& td, detail::tdata<> const&, static inline bool collect(TData& td, detail::tdata<> const& tr,
T0&& arg0, Ts&&... args) T0&& arg0, Ts&&... args)
{ {
td.set(std::forward<T0>(arg0), std::forward<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; return true;
} }
...@@ -415,6 +645,7 @@ class projection ...@@ -415,6 +645,7 @@ class projection
}; };
/*
template<class Pattern, class TargetSignature> template<class Pattern, class TargetSignature>
class projection<Pattern, TargetSignature, util::type_list<> > class projection<Pattern, TargetSignature, util::type_list<> >
{ {
...@@ -443,6 +674,7 @@ class projection<Pattern, TargetSignature, util::type_list<> > ...@@ -443,6 +674,7 @@ class projection<Pattern, TargetSignature, util::type_list<> >
} }
}; };
*/
template<class Expr, class Guard, class Transformers, class Pattern> template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl struct get_cfl
...@@ -492,15 +724,8 @@ struct invoke_helper2 ...@@ -492,15 +724,8 @@ struct invoke_helper2
template<typename... Args> template<typename... Args>
bool invoke(Args&&... args) const bool invoke(Args&&... args) const
{ {
typedef invoke_policy<get_wildcard_position<Pattern>(), Pattern> impl; typedef invoke_policy<Pattern> impl;
return impl::invoke(*this, std::forward<Args>(args)...); return impl::invoke(*this, std::forward<Args>(args)...);
// resolve arguments;
// helper4 encapsulates forwarding of (args...) to invoke_policy which
// calls operator()() of this object with resolved args
//invoke_helper4 fun;
// return fun(*this, std::forward<Args>(args)...);
} }
// resolved argument list (called from invoke_policy) // resolved argument list (called from invoke_policy)
template<typename... Args> template<typename... Args>
...@@ -1079,7 +1304,7 @@ size_t test__tuple() ...@@ -1079,7 +1304,7 @@ size_t test__tuple()
CPPA_CHECK_EQUAL("f02", invoked); CPPA_CHECK_EQUAL("f02", invoked);
invoked = ""; invoked = "";
auto f03 = _on(42, val<int>) >> [&](int a, int) { invoked = "f03"; CPPA_CHECK_EQUAL(42, a); }; auto f03 = _on(42, val<int>) >> [&](int const& a, int&) { invoked = "f03"; CPPA_CHECK_EQUAL(42, a); };
CPPA_CHECK_NOT_INVOKED(f03, (0, 0)); CPPA_CHECK_NOT_INVOKED(f03, (0, 0));
CPPA_CHECK_INVOKED(f03, (42, 42)); CPPA_CHECK_INVOKED(f03, (42, 42));
...@@ -1108,6 +1333,7 @@ size_t test__tuple() ...@@ -1108,6 +1333,7 @@ size_t test__tuple()
CPPA_CHECK_NOT_INVOKED(f07, (0)); CPPA_CHECK_NOT_INVOKED(f07, (0));
CPPA_CHECK_NOT_INVOKED(f07, (1)); CPPA_CHECK_NOT_INVOKED(f07, (1));
CPPA_CHECK_INVOKED(f07, (2)); CPPA_CHECK_INVOKED(f07, (2));
CPPA_CHECK(f07.invoke(make_any_tuple(2)));
int f08_val = 666; int f08_val = 666;
auto f08 = _on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; }; auto f08 = _on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; };
...@@ -1139,7 +1365,7 @@ size_t test__tuple() ...@@ -1139,7 +1365,7 @@ size_t test__tuple()
( (
_on<int>().when(_x1 < 10) >> [&]() { invoked = "f10.0"; }, _on<int>().when(_x1 < 10) >> [&]() { invoked = "f10.0"; },
_on<int>() >> [&]() { invoked = "f10.1"; }, _on<int>() >> [&]() { invoked = "f10.1"; },
_on<std::string>() >> [&]() { invoked = "f10.2"; } _on<std::string, anything>() >> [&](std::string&) { invoked = "f10.2"; }
); );
CPPA_CHECK(f10(9)); CPPA_CHECK(f10(9));
...@@ -1148,6 +1374,12 @@ size_t test__tuple() ...@@ -1148,6 +1374,12 @@ size_t test__tuple()
CPPA_CHECK_EQUAL("f10.1", invoked); CPPA_CHECK_EQUAL("f10.1", invoked);
CPPA_CHECK(f10("42")); CPPA_CHECK(f10("42"));
CPPA_CHECK_EQUAL("f10.2", invoked); CPPA_CHECK_EQUAL("f10.2", invoked);
CPPA_CHECK(f10("42", 42));
CPPA_CHECK(f10("a", "b", "c"));
std::string foobar = "foobar";
CPPA_CHECK(f10(foobar, "b", "c"));
CPPA_CHECK(f10("a", static_cast<std::string const&>(foobar), "b", "c"));
//CPPA_CHECK(f10(static_cast<std::string const&>(foobar), "b", "c"));
int f11_fun = 0; int f11_fun = 0;
auto f11 = pj_concat auto f11 = pj_concat
...@@ -1178,6 +1410,8 @@ size_t test__tuple() ...@@ -1178,6 +1410,8 @@ 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);
/* /*
VERBOSE(f00(42, 42)); VERBOSE(f00(42, 42));
VERBOSE(f01(42, 42)); VERBOSE(f01(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