Commit cc1c3445 authored by neverlord's avatar neverlord

pattern matching

parent 05b61ecf
......@@ -32,6 +32,7 @@
#define TDATA_HPP
#include <typeinfo>
#include <functional>
#include "cppa/get.hpp"
#include "cppa/option.hpp"
......@@ -44,6 +45,7 @@
#include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
......@@ -66,6 +68,36 @@ inline void* ptr_to(T* what) { return what; }
template<typename T>
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>
struct boxed_or_void
{
......@@ -78,8 +110,20 @@ struct boxed_or_void<util::void_type>
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...>
struct tdata;
......@@ -112,21 +156,27 @@ struct tdata<>
inline tdata(tdata&&) { }
inline tdata(tdata const&) { }
//// swallow "arg_match" silently
//constexpr tdata(util::wrapped<util::arg_match_t> const&) { }
inline size_t size() const { return num_elements; }
tdata<>& tail() { return *this; }
tdata<> const& tail() const { return *this; }
tdata<> const& ctail() const { return *this; }
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
{
throw std::out_of_range("");
throw std::out_of_range("tdata<>");
}
inline void set() { }
......@@ -187,7 +237,10 @@ struct tdata<Head, Tail...> : tdata<Tail...>
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;
......@@ -216,16 +269,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
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
// with traling extra arguments to initialize additional arguments
template<typename... Y>
tdata(tdata<Y...>& other) : super(other.tail()), head(other.head)
......@@ -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>
tdata& operator=(tdata<Y...> const& other)
{
......@@ -293,20 +301,39 @@ struct tdata<Head, Tail...> : tdata<Tail...>
super::set(std::forward<Args>(args)...);
}
inline size_t size() const { return num_elements; }
// upcast
inline tdata<Tail...>& tail() { 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
{
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>)
{
......
......@@ -108,7 +108,7 @@ class tuple_view : public abstract_tuple
void* mutable_at(size_t pos)
{
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
......
......@@ -322,12 +322,16 @@ struct ge_mutable_reference_wrapper
T* value;
ge_mutable_reference_wrapper() : value(nullptr) { }
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(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;
T& get() { CPPA_REQUIRE(value != 0); return *value; }
operator T& () { CPPA_REQUIRE(value != 0); return *value; }
T& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T& () const { CPPA_REQUIRE(value != 0); return *value; }
};
template<typename T>
......@@ -338,6 +342,11 @@ struct ge_reference_wrapper
ge_reference_wrapper() : value(nullptr) { }
ge_reference_wrapper(T const& val_ref) : value(&val_ref) { }
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;
T const& get() 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>
ge_reference_wrapper(bool const& val_ref) : value(&val_ref) { }
ge_reference_wrapper(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
bool get() const { return *value; }
operator bool () const { return *value; }
bool operator()() const { return *value; }
bool get() const { CPPA_REQUIRE(value != 0); return *value; }
operator bool () const { CPPA_REQUIRE(value != 0); return *value; }
bool operator()() const { CPPA_REQUIRE(value != 0); return *value; }
};
/**
......
......@@ -53,6 +53,16 @@ struct static_foreach_impl
::_ref(c, f, std::forward<Args>(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)
{
return f(get<Begin>(c), std::forward<Args>(args)...)
......@@ -76,6 +86,8 @@ struct static_foreach_impl<false, X, Y>
template<typename... Args>
static inline void _ref(Args&&...) { }
template<typename... Args>
static inline void _auto(Args&&...) { }
template<typename... Args>
static inline bool eval(Args&&...) { return true; }
template<typename... Args>
static inline bool eval_or(Args&&...) { return false; }
......
......@@ -243,7 +243,15 @@ struct tl_find_if
// list first_n(size_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>
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;
};
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.
*/
......
......@@ -81,15 +81,26 @@ struct invoke_policy_helper
AbstractTuple& tup;
invoke_policy_helper(AbstractTuple& tp) : i(0), tup(tp) { }
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>
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>
......@@ -104,23 +115,21 @@ struct gref_mutable_wrapped
typedef ge_mutable_reference_wrapper<T> type;
};
template<class NativeData, class WrappedRefs, class WrappedRefsForwarding>
struct invoke_policy_token
{
typedef NativeData native_type;
typedef WrappedRefs wrapped_refs;
typedef WrappedRefsForwarding wrapped_refs_fwd;
};
template<wildcard_position, class Pattern>
struct invoke_policy;
template<wildcard_position, class Pattern, class FilteredPattern>
struct invoke_policy_impl;
template<class Pattern>
struct invoke_policy<wildcard_position::nil, Pattern>
template<class Pattern, class FilteredPattern>
struct invoke_policy_impl<wildcard_position::nil, Pattern, FilteredPattern>
{
typedef Pattern filtered_pattern;
typedef typename detail::tdata_from_type_list<Pattern>::type native_data_type;
typedef typename detail::static_types_array_from_type_list<Pattern>::type arr_type;
typedef typename detail::tdata_from_type_list<
FilteredPattern
>::type
native_data_type;
typedef typename detail::static_types_array_from_type_list<
FilteredPattern
>::type
arr_type;
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, true>,
......@@ -128,14 +137,16 @@ struct invoke_policy<wildcard_position::nil, Pattern>
{
return target(std::forward<Ts>(args)...);
}
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(Target& target, Ts&&... args)
static bool invoke_args(Target& target, Ts&&... args)
{
typedef util::type_list<typename util::rm_ref<Ts>::type...> incoming;
std::integral_constant<bool, std::is_same<incoming, Pattern>::value>
......@@ -143,19 +154,26 @@ struct invoke_policy<wildcard_position::nil, Pattern>
return _invoke_args(token, target, std::forward<Ts>(args)...);
}
template<class PolicyToken, class Target, typename NativeArg, typename AbstractTuple>
static bool _invoke_tuple(PolicyToken,
Target& target,
template<class Target, typename NativeArg, typename Tuple>
static bool invoke_tuple(Target& target,
std::type_info const& arg_types,
detail::tuple_impl_info timpl,
NativeArg native_arg,
AbstractTuple& tup)
Tuple& tup)
{
if (arg_types == typeid(filtered_pattern))
if (arg_types == typeid(FilteredPattern))
{
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);
}
// 'fall through'
......@@ -163,11 +181,11 @@ struct invoke_policy<wildcard_position::nil, Pattern>
else if (timpl == detail::dynamically_typed)
{
auto& arr = arr_type::arr;
if (tup.size() != filtered_pattern::size)
if (tup.size() != FilteredPattern::size)
{
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))
{
......@@ -180,52 +198,222 @@ struct invoke_policy<wildcard_position::nil, Pattern>
{
return false;
}
// either dynamically typed or statically typed but not a native tuple
typename PolicyToken::wrapped_refs ttup;
invoke_policy_helper<AbstractTuple> iph{tup};
util::static_foreach<0, filtered_pattern::size>::_ref(ttup, iph);
// Tup::types is a type list with const qualified types if
// Tup represents 'encapsulated arguments'
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);
typename PolicyToken::wrapped_refs_fwd ttup_fwd = ttup;
ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
}
};
template<class Target>
static bool invoke(Target& target,
std::type_info const& arg_types,
detail::tuple_impl_info timpl,
void const* native_arg,
detail::abstract_tuple const& tup)
{
template<wildcard_position, class Tuple, class FilteredPattern>
struct deduce_tup_type;
template<class Tuple, class FilteredPattern>
struct deduce_tup_type<wildcard_position::trailing, Tuple, FilteredPattern>
{
typedef typename detail::tdata_from_type_list<
typename util::tl_map<
filtered_pattern,
gref_wrapped
typename util::tl_first_n<
typename Tuple::types,
FilteredPattern::size
>::type,
gref_mutable_wrapped
>::type
>::type
wrapped_refs;
invoke_policy_token<native_data_type const*,
wrapped_refs,
wrapped_refs const& > token;
return _invoke_tuple(token, target, arg_types, timpl, native_arg, tup);
}
template<typename Target>
static bool invoke(Target& target,
std::type_info const& arg_types,
detail::tuple_impl_info timpl,
void* native_arg,
detail::abstract_tuple& tup)
{
type;
typedef typename util::if_else<
std::is_const<Tuple>,
type const&,
util::wrapped<type&>
>::type
ref_type;
};
template<class FilteredPattern>
struct deduce_tup_type<wildcard_position::trailing, detail::abstract_tuple, FilteredPattern>
{
typedef typename detail::tdata_from_type_list<
typename util::tl_map<
filtered_pattern,
FilteredPattern,
gref_mutable_wrapped
>::type
>::type
wrapped_refs;
invoke_policy_token<native_data_type*,
wrapped_refs,
wrapped_refs& > token;
return _invoke_tuple(token, target, arg_types, timpl, native_arg, tup);
type;
typedef type& ref_type;
};
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
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>.
*/
template<class PartialFun, typename... Args>
bool operator()(PartialFun& fun, Args&&... args) const
{
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming;
std::integral_constant<
bool,
std::is_same<filtered_pattern_type, incoming>::value
sizeof...(Args) == filtered_pattern_type::size
> token;
return _arg_impl(token, fun, std::forward<Args>(args)...);
return _arg_fwd(token, fun, std::forward<Args>(args)...);
}
private:
template<class Storage, typename T>
static inline bool fetch_(Storage& storage, T&& value)
template<typename Storage, typename T>
static inline bool fetch_(Storage& storage, T& value)
{
storage = std::forward<T>(value);
storage = value;
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>
static inline bool fetch_(Storage& storage, option<Storage>&& value)
{
......@@ -398,10 +626,12 @@ class projection
}
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)
{
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;
}
......@@ -415,6 +645,7 @@ class projection
};
/*
template<class Pattern, class TargetSignature>
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>
struct get_cfl
......@@ -492,15 +724,8 @@ struct invoke_helper2
template<typename... Args>
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)...);
// 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)
template<typename... Args>
......@@ -1079,7 +1304,7 @@ size_t test__tuple()
CPPA_CHECK_EQUAL("f02", 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_INVOKED(f03, (42, 42));
......@@ -1108,6 +1333,7 @@ size_t test__tuple()
CPPA_CHECK_NOT_INVOKED(f07, (0));
CPPA_CHECK_NOT_INVOKED(f07, (1));
CPPA_CHECK_INVOKED(f07, (2));
CPPA_CHECK(f07.invoke(make_any_tuple(2)));
int f08_val = 666;
auto f08 = _on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; };
......@@ -1139,7 +1365,7 @@ size_t test__tuple()
(
_on<int>().when(_x1 < 10) >> [&]() { invoked = "f10.0"; },
_on<int>() >> [&]() { invoked = "f10.1"; },
_on<std::string>() >> [&]() { invoked = "f10.2"; }
_on<std::string, anything>() >> [&](std::string&) { invoked = "f10.2"; }
);
CPPA_CHECK(f10(9));
......@@ -1148,6 +1374,12 @@ size_t test__tuple()
CPPA_CHECK_EQUAL("f10.1", invoked);
CPPA_CHECK(f10("42"));
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;
auto f11 = pj_concat
......@@ -1178,6 +1410,8 @@ size_t test__tuple()
CPPA_CHECK(f11("10"));
CPPA_CHECK_EQUAL(10, f11_fun);
//exit(0);
/*
VERBOSE(f00(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