Commit 8f393dc7 authored by neverlord's avatar neverlord

pattern matching

parent 7ee5a950
...@@ -173,10 +173,12 @@ nobase_library_include_HEADERS = \ ...@@ -173,10 +173,12 @@ nobase_library_include_HEADERS = \
cppa/serializer.hpp \ cppa/serializer.hpp \
cppa/stacked_event_based_actor.hpp \ cppa/stacked_event_based_actor.hpp \
cppa/to_string.hpp \ cppa/to_string.hpp \
cppa/tpartial_function.hpp \
cppa/tuple_cast.hpp \ cppa/tuple_cast.hpp \
cppa/type_value_pair.hpp \ cppa/type_value_pair.hpp \
cppa/uniform_type_info.hpp \ cppa/uniform_type_info.hpp \
cppa/util/abstract_uniform_type_info.hpp \ cppa/util/abstract_uniform_type_info.hpp \
cppa/util/apply_args.hpp \
cppa/util/apply_tuple.hpp \ cppa/util/apply_tuple.hpp \
cppa/util/arg_match_t.hpp \ cppa/util/arg_match_t.hpp \
cppa/util/at.hpp \ cppa/util/at.hpp \
...@@ -201,11 +203,13 @@ nobase_library_include_HEADERS = \ ...@@ -201,11 +203,13 @@ nobase_library_include_HEADERS = \
cppa/util/is_manipulator.hpp \ cppa/util/is_manipulator.hpp \
cppa/util/is_mutable_ref.hpp \ cppa/util/is_mutable_ref.hpp \
cppa/util/is_primitive.hpp \ cppa/util/is_primitive.hpp \
cppa/util/left_or_right.hpp \
cppa/util/producer_consumer_list.hpp \ cppa/util/producer_consumer_list.hpp \
cppa/util/pt_dispatch.hpp \ cppa/util/pt_dispatch.hpp \
cppa/util/pt_token.hpp \ cppa/util/pt_token.hpp \
cppa/util/replace_type.hpp \ cppa/util/replace_type.hpp \
cppa/util/ripemd_160.hpp \ cppa/util/ripemd_160.hpp \
cppa/util/rm_option.hpp \
cppa/util/rm_ref.hpp \ cppa/util/rm_ref.hpp \
cppa/util/shared_lock_guard.hpp \ cppa/util/shared_lock_guard.hpp \
cppa/util/shared_spinlock.hpp \ cppa/util/shared_spinlock.hpp \
......
...@@ -258,3 +258,7 @@ cppa/detail/matches.hpp ...@@ -258,3 +258,7 @@ cppa/detail/matches.hpp
unit_testing/test__match.cpp unit_testing/test__match.cpp
cppa/guard_expr.hpp cppa/guard_expr.hpp
src/pattern.cpp src/pattern.cpp
cppa/util/left_or_right.hpp
cppa/util/apply_args.hpp
cppa/tpartial_function.hpp
cppa/util/rm_option.hpp
...@@ -186,6 +186,11 @@ class any_tuple ...@@ -186,6 +186,11 @@ class any_tuple
return any_tuple{simple_view(std::forward<T>(value), token)}; return any_tuple{simple_view(std::forward<T>(value), token)};
} }
void force_detach()
{
m_vals.detach();
}
void reset(); void reset();
private: private:
......
...@@ -89,6 +89,11 @@ class cow_ptr ...@@ -89,6 +89,11 @@ class cow_ptr
return *this; return *this;
} }
void detach()
{
(void) detached_ptr();
}
inline void reset(T* value = nullptr) { m_ptr.reset(value); } inline void reset(T* value = nullptr) { m_ptr.reset(value); }
inline T* get() { return (m_ptr) ? detached_ptr() : nullptr; } inline T* get() { return (m_ptr) ? detached_ptr() : nullptr; }
......
...@@ -61,6 +61,7 @@ class abstract_tuple : public ref_counted ...@@ -61,6 +61,7 @@ class abstract_tuple : public ref_counted
// mutators // mutators
virtual void* mutable_at(size_t pos) = 0; virtual void* mutable_at(size_t pos) = 0;
virtual void* mutable_native_data();
// accessors // accessors
virtual size_t size() const = 0; virtual size_t size() const = 0;
......
...@@ -65,7 +65,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor ...@@ -65,7 +65,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor
F m_fun; F m_fun;
typedef typename tdata_from_type_list< typedef typename tdata_from_type_list<
typename util::tl_apply<util::type_list<Args...>, typename util::tl_map<util::type_list<Args...>,
implicit_conversions>::type>::type implicit_conversions>::type>::type
tdata_type; tdata_type;
...@@ -104,7 +104,7 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor ...@@ -104,7 +104,7 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor
F m_fun; F m_fun;
typedef typename tdata_from_type_list< typedef typename tdata_from_type_list<
typename util::tl_apply<util::type_list<Args...>, typename util::tl_map<util::type_list<Args...>,
implicit_conversions>::type>::type implicit_conversions>::type>::type
tdata_type; tdata_type;
......
...@@ -274,7 +274,7 @@ template<typename Fun, class Pattern> ...@@ -274,7 +274,7 @@ template<typename Fun, class Pattern>
struct select_invokable_impl struct select_invokable_impl
{ {
typedef typename util::get_arg_types<Fun>::types qualified_arg_types; typedef typename util::get_arg_types<Fun>::types qualified_arg_types;
typedef typename util::tl_apply<qualified_arg_types, util::rm_ref>::type typedef typename util::tl_map<qualified_arg_types, util::rm_ref>::type
arg_types; arg_types;
static constexpr mapping_policy mp = get_mapping_policy<arg_types>(); static constexpr mapping_policy mp = get_mapping_policy<arg_types>();
typedef invokable_impl<Fun, pattern_policy<mp, Pattern> > type; typedef invokable_impl<Fun, pattern_policy<mp, Pattern> > type;
...@@ -284,7 +284,7 @@ template<typename Fun> ...@@ -284,7 +284,7 @@ template<typename Fun>
struct select_invokable_impl<Fun, pattern<anything> > struct select_invokable_impl<Fun, pattern<anything> >
{ {
typedef typename util::get_arg_types<Fun>::types qualified_arg_types; typedef typename util::get_arg_types<Fun>::types qualified_arg_types;
typedef typename util::tl_apply<qualified_arg_types, util::rm_ref>::type typedef typename util::tl_map<qualified_arg_types, util::rm_ref>::type
arg_types; arg_types;
typedef typename util::rm_ref<typename arg_types::head>::type arg0; typedef typename util::rm_ref<typename arg_types::head>::type arg0;
static_assert(arg_types::size < 2, "functor has too many arguments"); static_assert(arg_types::size < 2, "functor has too many arguments");
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "cppa/util/disable_if.hpp" #include "cppa/util/disable_if.hpp"
#include "cppa/util/arg_match_t.hpp" #include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/boxed.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"
...@@ -65,6 +66,18 @@ inline void* ptr_to(T* what) { return what; } ...@@ -65,6 +66,18 @@ 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>
struct boxed_or_void
{
static constexpr bool value = is_boxed<T>::value;
};
template<>
struct boxed_or_void<util::void_type>
{
static constexpr bool value = true;
};
/* /*
* "enhanced std::tuple" * "enhanced std::tuple"
*/ */
...@@ -82,16 +95,25 @@ struct tdata<> ...@@ -82,16 +95,25 @@ struct tdata<>
typedef util::void_type back_type; typedef util::void_type back_type;
typedef util::type_list<> types; typedef util::type_list<> types;
static constexpr size_t tdata_size = 0; static constexpr size_t num_elements = 0;
constexpr tdata() { } constexpr tdata() { }
inline tdata(tdata&&) { } // swallow any number of additional boxed or void_type arguments silently
template<typename... Args>
tdata(Args&&...)
{
typedef util::type_list<typename util::rm_ref<Args>::type...> incoming;
static_assert(util::tl_forall<incoming, boxed_or_void>::value,
"Additional unboxed arguments provided");
}
inline tdata(tdata&) { }
inline tdata(tdata&&) { }
inline tdata(tdata const&) { } inline tdata(tdata const&) { }
// swallow "arg_match" silently //// swallow "arg_match" silently
constexpr tdata(util::wrapped<util::arg_match_t> const&) { } //constexpr tdata(util::wrapped<util::arg_match_t> const&) { }
tdata<>& tail() { return *this; } tdata<>& tail() { return *this; }
...@@ -113,6 +135,49 @@ struct tdata<> ...@@ -113,6 +135,49 @@ struct tdata<>
}; };
template<bool IsBoxed, bool IsFunction, typename Head, typename T>
struct td_filter_
{
static inline T const& _(T const& arg) { return arg; }
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
};
template<typename Head, typename T>
struct td_filter_<false, true, Head, T>
{
static inline T* _(T* arg) { return arg; }
};
template<typename Head, typename T>
struct td_filter_<true, false, Head, T>
{
static inline Head _(T const&) { return Head{}; }
};
template<typename Head, typename T>
struct td_filter_<true, true, Head, T> : td_filter_<true, false, Head, T>
{
};
template<typename Head, typename T>
auto td_filter(T&& arg)
-> decltype(
td_filter_<
is_boxed<typename util::rm_ref<T>::type>::value,
std::is_function<typename util::rm_ref<T>::type>::value,
Head,
typename util::rm_ref<T>::type
>::_(std::forward<T>(arg)))
{
return td_filter_<
is_boxed<typename util::rm_ref<T>::type>::value,
std::is_function<typename util::rm_ref<T>::type>::value,
Head,
typename util::rm_ref<T>::type
>::_(std::forward<T>(arg));
}
template<typename... X, typename... Y> template<typename... X, typename... Y>
void tdata_set(tdata<X...>& rhs, tdata<Y...> const& lhs); void tdata_set(tdata<X...>& rhs, tdata<Y...> const& lhs);
...@@ -126,7 +191,7 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -126,7 +191,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
Head head; Head head;
static constexpr size_t tdata_size = (sizeof...(Tail) + 1); static constexpr size_t num_elements = (sizeof...(Tail) + 1);
typedef Head head_type; typedef Head head_type;
typedef tdata<Tail...> tail_type; typedef tdata<Tail...> tail_type;
...@@ -142,23 +207,31 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -142,23 +207,31 @@ struct tdata<Head, Tail...> : tdata<Tail...>
//tdata(Head const& v0, Tail const&... vals) : super(vals...), head(v0) { } //tdata(Head const& v0, Tail const&... vals) : super(vals...), head(v0) { }
template<typename Arg0, typename... Args>
tdata(Arg0&& arg0, Args&&... args)
: super(std::forward<Args>(args)...)
, head(td_filter<Head>(std::forward<Arg0>(arg0)))
{
}
tdata(tdata const&) = default;
// allow partial initialization // allow partial initialization
template<typename... Args> //template<typename... Args>
tdata(Head const& v0, Args const&... vals) : super(vals...), head(v0) { } //tdata(Head const& v0, Args const&... vals) : super(vals...), head(v0) { }
// allow partial initialization // allow partial initialization
template<typename... Args> //template<typename... Args>
tdata(Head&& v0, Args const&... vals) : super(vals...), head(std::move(v0)) { } //tdata(Head&& v0, Args const&... vals) : super(vals...), head(std::move(v0)) { }
// allow initialization with wrapped<Head> (uses the default constructor) // allow (partial) initialization from a different tdata
template<typename... Args> // with traling extra arguments to initialize additional arguments
tdata(util::wrapped<Head> const&, Args const&... vals)
: super(vals...), head() template<typename... Y>
tdata(tdata<Y...>& other) : super(other.tail()), head(other.head)
{ {
} }
// allow (partial) initialization from a different tdata
// with traling extra arguments to initialize additional arguments
template<typename... Y> template<typename... Y>
tdata(tdata<Y...> const& other) : super(other.tail()), head(other.head) tdata(tdata<Y...> const& other) : super(other.tail()), head(other.head)
{ {
...@@ -170,6 +243,7 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -170,6 +243,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
{ {
} }
/*
template<typename... Y> template<typename... Y>
tdata(Head const& arg, tdata<Y...> const& other) tdata(Head const& arg, tdata<Y...> const& other)
: super(other), head(arg) : super(other), head(arg)
...@@ -203,14 +277,7 @@ struct tdata<Head, Tail...> : tdata<Tail...> ...@@ -203,14 +277,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
: super(), head(other.head, arg) : super(), head(other.head, arg)
{ {
} }
*/
// allow initialization with a function pointer or reference
// returning a wrapped<Head>
template<typename...Args>
tdata(util::wrapped<Head>(*)(), Args const&... vals)
: super(vals...), head()
{
}
template<typename... Y> template<typename... Y>
tdata& operator=(tdata<Y...> const& other) tdata& operator=(tdata<Y...> const& other)
......
...@@ -73,6 +73,11 @@ class tuple_vals : public abstract_tuple ...@@ -73,6 +73,11 @@ class tuple_vals : public abstract_tuple
return &m_data; return &m_data;
} }
void* mutable_native_data()
{
return &m_data;
}
inline data_type& data() inline data_type& data()
{ {
return m_data; return m_data;
......
...@@ -46,11 +46,11 @@ template<typename...> class cow_tuple; ...@@ -46,11 +46,11 @@ template<typename...> class cow_tuple;
// forward declaration of get(detail::tdata<...> const&) // forward declaration of get(detail::tdata<...> const&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(detail::tdata<Tn...> const&); typename util::at<N, Tn...>::type const& get(detail::tdata<Tn...> const&);
// forward declarations of get(tuple<...> const&) // forward declarations of get(tuple<...> const&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
const typename util::at<N, Tn...>::type& get(cow_tuple<Tn...> const&); typename util::at<N, Tn...>::type const& get(cow_tuple<Tn...> const&);
// forward declarations of get_ref(detail::tdata<...>&) // forward declarations of get_ref(detail::tdata<...>&)
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
...@@ -60,6 +60,13 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&); ...@@ -60,6 +60,13 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
template<size_t N, typename... Tn> template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(cow_tuple<Tn...>&); typename util::at<N, Tn...>::type& get_ref(cow_tuple<Tn...>&);
// support container-like access for type lists containing tokens
template<size_t N, typename... Ts>
typename util::at<N, Ts...>::type get(util::type_list<Ts...> const&)
{
return {};
}
} // namespace cppa } // namespace cppa
#endif // GET_HPP #endif // GET_HPP
...@@ -37,8 +37,12 @@ ...@@ -37,8 +37,12 @@
#include <functional> #include <functional>
#include <type_traits> #include <type_traits>
#include "cppa/config.hpp"
#include "cppa/util/at.hpp" #include "cppa/util/at.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/enable_if.hpp" #include "cppa/util/enable_if.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/detail/tdata.hpp" #include "cppa/detail/tdata.hpp"
...@@ -54,6 +58,8 @@ enum operator_id ...@@ -54,6 +58,8 @@ enum operator_id
logical_and_op, logical_or_op, logical_and_op, logical_or_op,
// pseudo operators for function invocation // pseudo operators for function invocation
exec_fun1_op, exec_fun2_op, exec_fun3_op, exec_fun1_op, exec_fun2_op, exec_fun3_op,
// operator to invoke a given functor with all arguments forwarded
exec_xfun_op,
// pseudo operator to store function parameters // pseudo operator to store function parameters
dummy_op dummy_op
}; };
...@@ -157,6 +163,15 @@ typename gbind3<Fun, T1, T2, T3>::result gbind(Fun fun, T1 t1, T2 t2, T3 t3) ...@@ -157,6 +163,15 @@ typename gbind3<Fun, T1, T2, T3>::result gbind(Fun fun, T1 t1, T2 t2, T3 t3)
return {fun, t1, t2, t3}; return {fun, t1, t2, t3};
} }
/**
* @brief Call wrapper for any given functor returning a boolean.
*/
template<typename Fun>
guard_expr<exec_xfun_op, Fun, util::void_type> gcall(Fun fun)
{
return {fun, util::void_type{}};
}
struct ge_search_container struct ge_search_container
{ {
bool sc; bool sc;
...@@ -301,6 +316,20 @@ struct guard_placeholder ...@@ -301,6 +316,20 @@ struct guard_placeholder
}; };
template<typename T>
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=(ge_mutable_reference_wrapper const&) = default;
T& get() { CPPA_REQUIRE(value != 0); return *value; }
operator T& () { CPPA_REQUIRE(value != 0); return *value; }
};
template<typename T> template<typename T>
struct ge_reference_wrapper struct ge_reference_wrapper
{ {
...@@ -310,8 +339,8 @@ struct ge_reference_wrapper ...@@ -310,8 +339,8 @@ struct ge_reference_wrapper
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=(ge_reference_wrapper const&) = default; ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
T const& get() const { return *value; } T const& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T const& () const { return *value; } operator T const& () const { CPPA_REQUIRE(value != 0); return *value; }
}; };
// support use of gref(BooleanVariable) as receive loop 'guard' // support use of gref(BooleanVariable) as receive loop 'guard'
...@@ -352,11 +381,11 @@ struct ge_unbound<ge_reference_wrapper<T>, Tuple> ...@@ -352,11 +381,11 @@ struct ge_unbound<ge_reference_wrapper<T>, Tuple>
// unbound type of placeholder // unbound type of placeholder
template<int X, typename... Ts> template<int X, typename... Ts>
struct ge_unbound<guard_placeholder<X>, detail::tdata<Ts...> > struct ge_unbound<guard_placeholder<X>, detail::tdata<std::reference_wrapper<Ts>...> >
{ {
static_assert(X < sizeof...(Ts), static_assert(X < sizeof...(Ts),
"Cannot unbind placeholder (too few arguments)"); "Cannot unbind placeholder (too few arguments)");
typedef typename std::remove_pointer<typename util::at<X, Ts...>::type>::type type; typedef typename util::at<X, Ts...>::type type;
}; };
// operators, operators, operators // operators, operators, operators
...@@ -435,6 +464,12 @@ struct ge_result_<guard_expr<OP, First, Second>, Tuple> ...@@ -435,6 +464,12 @@ struct ge_result_<guard_expr<OP, First, Second>, Tuple>
*static_cast<rhs_type const*>(nullptr))) type; *static_cast<rhs_type const*>(nullptr))) type;
}; };
template<typename Fun, class Tuple>
struct ge_result_<guard_expr<exec_xfun_op, Fun, util::void_type>, Tuple>
{
typedef bool type;
};
template<typename First, typename Second, class Tuple> template<typename First, typename Second, class Tuple>
struct ge_result_<guard_expr<exec_fun1_op, First, Second>, Tuple> struct ge_result_<guard_expr<exec_fun1_op, First, Second>, Tuple>
{ {
...@@ -516,9 +551,9 @@ inline T const& ge_resolve(Tuple const&, ge_reference_wrapper<T> const& value) ...@@ -516,9 +551,9 @@ inline T const& ge_resolve(Tuple const&, ge_reference_wrapper<T> const& value)
template<class Tuple, int X> template<class Tuple, int X>
inline auto ge_resolve(Tuple const& tup, guard_placeholder<X>) inline auto ge_resolve(Tuple const& tup, guard_placeholder<X>)
-> decltype(*get<X>(tup)) -> decltype(get<X>(tup).get())
{ {
return *get<X>(tup); return get<X>(tup).get();
} }
template<class Tuple, operator_id OP, typename First, typename Second> template<class Tuple, operator_id OP, typename First, typename Second>
...@@ -557,6 +592,15 @@ struct ge_eval_<logical_or_op, Tuple, First, Second> ...@@ -557,6 +592,15 @@ struct ge_eval_<logical_or_op, Tuple, First, Second>
} }
}; };
template<class Tuple, typename Fun>
struct ge_eval_<exec_xfun_op, Tuple, Fun, util::void_type>
{
static inline bool _(Tuple const& tup, Fun const& fun, util::void_type const&)
{
return util::unchecked_apply_tuple<bool>(fun, tup);
}
};
template<class Tuple, typename First, typename Second> template<class Tuple, typename First, typename Second>
struct ge_eval_<exec_fun1_op, Tuple, First, Second> struct ge_eval_<exec_fun1_op, Tuple, First, Second>
{ {
...@@ -618,9 +662,10 @@ auto ge_invoke_step2(guard_expr<OP, First, Second> const& ge, ...@@ -618,9 +662,10 @@ auto ge_invoke_step2(guard_expr<OP, First, Second> const& ge,
template<operator_id OP, typename First, typename Second, typename... Args> template<operator_id OP, typename First, typename Second, typename... Args>
auto ge_invoke(guard_expr<OP, First, Second> const& ge, auto ge_invoke(guard_expr<OP, First, Second> const& ge,
Args const&... args) Args const&... args)
-> typename ge_result<OP, First, Second, detail::tdata<Args*...>>::type -> typename ge_result<OP, First, Second,
detail::tdata<std::reference_wrapper<const Args>...>>::type
{ {
detail::tdata<Args const*...> tup{&args...}; detail::tdata<std::reference_wrapper<const Args>...> tup{args...};
return ge_invoke_step2(ge, tup); return ge_invoke_step2(ge, tup);
} }
...@@ -630,7 +675,7 @@ struct ge_invoke_helper ...@@ -630,7 +675,7 @@ struct ge_invoke_helper
GuardExpr const& ge; GuardExpr const& ge;
ge_invoke_helper(GuardExpr const& arg) : ge(arg) { } ge_invoke_helper(GuardExpr const& arg) : ge(arg) { }
template<typename... Args> template<typename... Args>
bool operator()(Args&&... args) bool operator()(Args&&... args) const
{ {
return ge_invoke(ge, std::forward<Args>(args)...); return ge_invoke(ge, std::forward<Args>(args)...);
} }
......
...@@ -117,7 +117,7 @@ class rvalue_builder ...@@ -117,7 +117,7 @@ class rvalue_builder
typedef typename get_callable_trait<F>::type ctrait; typedef typename get_callable_trait<F>::type ctrait;
typedef typename ctrait::arg_types raw_arg_types; typedef typename ctrait::arg_types raw_arg_types;
static_assert(raw_types::size > 0, "functor has no arguments"); static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_arg_types,rm_ref>::type arg_types; typedef typename tl_map<raw_arg_types,rm_ref>::type arg_types;
typedef typename tl_concat<types,arg_types>::type full_types; typedef typename tl_concat<types,arg_types>::type full_types;
typedef typename pattern_from_type_list<full_types>::type epattern; typedef typename pattern_from_type_list<full_types>::type epattern;
return get_invokable_impl<epattern>(std::forward<F>(f), return get_invokable_impl<epattern>(std::forward<F>(f),
...@@ -231,7 +231,7 @@ class on_the_fly_rvalue_builder ...@@ -231,7 +231,7 @@ class on_the_fly_rvalue_builder
typedef typename get_callable_trait<F>::type ctrait; typedef typename get_callable_trait<F>::type ctrait;
typedef typename ctrait::arg_types raw_types; typedef typename ctrait::arg_types raw_types;
static_assert(raw_types::size > 0, "functor has no arguments"); static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_types,rm_ref>::type types; typedef typename tl_map<raw_types,rm_ref>::type types;
typedef typename pattern_from_type_list<types>::type pattern_type; typedef typename pattern_from_type_list<types>::type pattern_type;
return get_invokable_impl<pattern_type>(std::forward<F>(f)); return get_invokable_impl<pattern_type>(std::forward<F>(f));
} }
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef TPARTIAL_FUNCTION_HPP
#define TPARTIAL_FUNCTION_HPP
#include <cstddef>
#include <type_traits>
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_args.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/util/is_mutable_ref.hpp"
namespace cppa {
template<class Expr, class Guard, typename Result, typename... Args>
class tpartial_function
{
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types ctrait_args;
static_assert(util::tl_exists<util::type_list<Args...>,
std::is_rvalue_reference >::value == false,
"partial functions using rvalue arguments are not supported");
public:
typedef util::type_list<Args...> arg_types;
static constexpr size_t num_arguments = sizeof...(Args);
static constexpr bool manipulates_args =
util::tl_exists<arg_types, util::is_mutable_ref>::value;
template<typename Fun, typename... G>
tpartial_function(Fun&& fun, G&&... guard_args)
: m_guard(std::forward<G>(guard_args)...)
, m_expr(std::forward<Fun>(fun))
{
}
tpartial_function(tpartial_function&& other)
: m_guard(std::move(other.m_guard))
, m_expr(std::move(other.m_expr))
{
}
tpartial_function(tpartial_function const&) = default;
bool defined_at(typename util::rm_ref<Args>::type const&... args) const
{
return m_guard(args...);
}
Result operator()(Args... args) const
{
return util::apply_args<Result, ctrait_args::size, sizeof...(Args)>
::_(m_expr, args...);
}
private:
Guard m_guard;
Expr m_expr;
};
template<class Expr, class Guard, typename Args,
typename Result = util::void_type, size_t Step = 0>
struct get_tpartial_function;
template<class Expr, class Guard, typename... Args, typename Result>
struct get_tpartial_function<Expr, Guard, util::type_list<Args...>, Result, 1>
{
typedef tpartial_function<Expr, Guard, Result, Args...> type;
};
template<class Expr, class Guard, typename... Args>
struct get_tpartial_function<Expr, Guard,
util::type_list<Args...>, util::void_type, 0>
{
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename ctrait::arg_types arg_types;
static_assert(arg_types::size <= sizeof...(Args),
"Functor takes too much arguments");
typedef typename get_tpartial_function<
Expr,
Guard,
// fill arg_types of Expr from left with const Args&
typename util::tl_zip<
typename util::tl_pad_left<
typename ctrait::arg_types,
sizeof...(Args)
>::type,
util::type_list<Args const&...>,
util::left_or_right
>::type,
typename ctrait::result_type,
1
>::type
type;
};
} // namespace cppa
#endif // TPARTIAL_FUNCTION_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef APPLY_ARGS_HPP
#define APPLY_ARGS_HPP
#include <cstddef>
namespace cppa { namespace util {
template<typename Result, size_t NumFunctorArgs, size_t NumArgs>
struct apply_args
{
template<class Fun, typename Arg0, typename... Args>
static Result _(Fun const& fun, Arg0&&, Args&&... args)
{
return apply_args<Result, NumFunctorArgs, sizeof...(Args)>
::_(fun, std::forward<Args>(args)...);
}
};
template<typename Result, size_t X>
struct apply_args<Result, X, X>
{
template<class Fun, typename... Args>
static Result _(Fun const& fun, Args&&... args)
{
return fun(std::forward<Args>(args)...);
}
};
} } // namespace cppa::util
#endif // APPLY_ARGS_HPP
...@@ -43,7 +43,7 @@ template<typename Result, bool IsManipulator, size_t... Range> ...@@ -43,7 +43,7 @@ template<typename Result, bool IsManipulator, size_t... Range>
struct apply_tuple_impl struct apply_tuple_impl
{ {
template<typename F, template<typename...> class Tuple, typename... T> template<typename F, template<typename...> class Tuple, typename... T>
static Result apply(F&& f, Tuple<T...> const& args) static Result apply(F& f, Tuple<T...> const& args)
{ {
return f(get<Range>(args)...); return f(get<Range>(args)...);
} }
...@@ -53,7 +53,7 @@ template<typename Result, size_t... Range> ...@@ -53,7 +53,7 @@ template<typename Result, size_t... Range>
struct apply_tuple_impl<Result, true, Range...> struct apply_tuple_impl<Result, true, Range...>
{ {
template<typename F, template<typename...> class Tuple, typename... T> template<typename F, template<typename...> class Tuple, typename... T>
static Result apply(F&& f, Tuple<T...>& args) static Result apply(F& f, Tuple<T...>& args)
{ {
return f(get_ref<Range>(args)...); return f(get_ref<Range>(args)...);
} }
...@@ -75,7 +75,7 @@ template<typename Result, bool IsManipulator> ...@@ -75,7 +75,7 @@ template<typename Result, bool IsManipulator>
struct apply_tuple_util<Result, IsManipulator, 1, 0> struct apply_tuple_util<Result, IsManipulator, 1, 0>
{ {
template<typename F, class Unused> template<typename F, class Unused>
static Result apply(F&& f, Unused const&) static Result apply(F& f, Unused const&)
{ {
return f(); return f();
} }
...@@ -119,6 +119,14 @@ Result unchecked_apply_tuple_in_range(F&& fun, Tuple<T...> const& tup) ...@@ -119,6 +119,14 @@ Result unchecked_apply_tuple_in_range(F&& fun, Tuple<T...> const& tup)
::apply(std::forward<F>(fun), tup); ::apply(std::forward<F>(fun), tup);
} }
template<typename Result, size_t From, size_t To,
typename F, template<typename...> class Tuple, typename... T>
Result unchecked_apply_tuple_in_range(F&& fun, Tuple<T...>& tup)
{
return apply_tuple_util<Result, true, From, To>
::apply(std::forward<F>(fun), tup);
}
// applies all values of @p tup to @p fun // applies all values of @p tup to @p fun
// does not evaluate result type of functor // does not evaluate result type of functor
template<typename Result, typename F, template<typename Result, typename F,
...@@ -129,6 +137,16 @@ Result unchecked_apply_tuple(F&& fun, Tuple<T...> const& tup) ...@@ -129,6 +137,16 @@ Result unchecked_apply_tuple(F&& fun, Tuple<T...> const& tup)
(std::forward<F>(fun), tup); (std::forward<F>(fun), tup);
} }
// applies all values of @p tup to @p fun
// does not evaluate result type of functor
template<typename Result, typename F,
template<typename...> class Tuple, typename... T>
Result unchecked_apply_tuple(F&& fun, Tuple<T...>& tup)
{
return unchecked_apply_tuple_in_range<Result, 0, sizeof...(T) - 1>
(std::forward<F>(fun), tup);
}
} } // namespace cppa::util } } // namespace cppa::util
#endif // APPLY_TUPLE_HPP #endif // APPLY_TUPLE_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef LEFT_OR_RIGHT_HPP
#define LEFT_OR_RIGHT_HPP
#include "cppa/util/void_type.hpp"
namespace cppa { namespace util {
/**
* @brief Evaluates to @p Right if @p Left == void_type, @p Left otherwise.
*/
template<typename Left, typename Right>
struct left_or_right
{
typedef Left type;
};
template<typename Right>
struct left_or_right<util::void_type, Right>
{
typedef Right type;
};
} } // namespace cppa::util
#endif // LEFT_OR_RIGHT_HPP
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \L\ \/\ \__/\ \ \L\ \ \ \L\ \/\ \L\.\_ *
* /\____\\ \_\ \_,__/\ \____\\ \ ,__/\ \ ,__/\ \__/.\_\ *
* \/____/ \/_/\/___/ \/____/ \ \ \/ \ \ \/ \/__/\/_/ *
* \ \_\ \ \_\ *
* \/_/ \/_/ *
* *
* Copyright (C) 2011, 2012 *
* Dominik Charousset <dominik.charousset@haw-hamburg.de> *
* *
* This file is part of libcppa. *
* libcppa is free software: you can redistribute it and/or modify it under *
* the terms of the GNU Lesser General Public License as published by the *
* Free Software Foundation, either version 3 of the License *
* or (at your option) any later version. *
* *
* libcppa is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
* See the GNU Lesser General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with libcppa. If not, see <http://www.gnu.org/licenses/>. *
\******************************************************************************/
#ifndef RM_OPTION_HPP
#define RM_OPTION_HPP
#include "cppa/option.hpp"
namespace cppa { namespace util {
template<typename T>
struct rm_option
{
typedef T type;
};
template<typename T>
struct rm_option<option<T> >
{
typedef T type;
};
} } // namespace cppa::util
#endif // RM_OPTION_HPP
...@@ -39,28 +39,32 @@ template<bool BeginLessEnd, size_t Begin, size_t End> ...@@ -39,28 +39,32 @@ template<bool BeginLessEnd, size_t Begin, size_t End>
struct static_foreach_impl struct static_foreach_impl
{ {
template<typename Container, typename Fun, typename... Args> template<typename Container, typename Fun, typename... Args>
static inline void _(Container const& c, Fun& f, Args const&... args) static inline void _(Container const& c, Fun& f, Args&&... args)
{ {
f(get<Begin>(c), args...); f(get<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>::_(c, f, args...); static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_(c, f, std::forward<Args>(args)...);
} }
template<typename Container, typename Fun, typename... Args> template<typename Container, typename Fun, typename... Args>
static inline void _ref(Container& c, Fun& f, Args const&... args) static inline void _ref(Container& c, Fun& f, Args&&... args)
{ {
f(get_ref<Begin>(c), args...); f(get_ref<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>::_ref(c, f, args...); static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_ref(c, f, std::forward<Args>(args)...);
} }
template<typename Container, typename Fun, typename... Args> template<typename Container, typename Fun, typename... Args>
static inline bool eval(Container const& c, Fun& f, Args const&... args) static inline bool eval(Container const& c, Fun& f, Args&&... args)
{ {
return f(get<Begin>(c), args...) return f(get<Begin>(c), std::forward<Args>(args)...)
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>::eval(c, f, args...); && static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval(c, f, std::forward<Args>(args)...);
} }
template<typename Container, typename Fun, typename... Args> template<typename Container, typename Fun, typename... Args>
static inline bool eval_or(Container const& c, Fun& f, Args const&... args) static inline bool eval_or(Container const& c, Fun& f, Args&&... args)
{ {
return f(get<Begin>(c), args...) return f(get<Begin>(c), std::forward<Args>(args)...)
|| static_foreach_impl<(Begin+1 < End), Begin+1, End>::eval_or(c, f, args...); || static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval_or(c, f, std::forward<Args>(args)...);
} }
}; };
...@@ -68,13 +72,13 @@ template<size_t X, size_t Y> ...@@ -68,13 +72,13 @@ template<size_t X, size_t Y>
struct static_foreach_impl<false, X, Y> struct static_foreach_impl<false, X, Y>
{ {
template<typename... Args> template<typename... Args>
static inline void _(Args const&...) { } static inline void _(Args&&...) { }
template<typename... Args> template<typename... Args>
static inline void _ref(Args const&...) { } static inline void _ref(Args&&...) { }
template<typename... Args> template<typename... Args>
static inline bool eval(Args const&...) { return true; } static inline bool eval(Args&&...) { return true; }
template<typename... Args> template<typename... Args>
static inline bool eval_or(Args const&...) { return false; } static inline bool eval_or(Args&&...) { return false; }
}; };
/** /**
......
...@@ -101,10 +101,7 @@ struct is_type_list<type_list<Ts...> > ...@@ -101,10 +101,7 @@ struct is_type_list<type_list<Ts...> >
static constexpr bool value = true; static constexpr bool value = true;
}; };
// static list list::zip(list, list) // static list zip(list, list)
template<class ListA, class ListB>
struct tl_zip;
/** /**
* @brief Zips two lists of equal size. * @brief Zips two lists of equal size.
...@@ -113,17 +110,31 @@ struct tl_zip; ...@@ -113,17 +110,31 @@ struct tl_zip;
* e.g., tl_zip<type_list<int,double>,type_list<float,string>>::type * e.g., tl_zip<type_list<int,double>,type_list<float,string>>::type
* is type_list<type_pair<int,float>,type_pair<double,string>>. * is type_list<type_pair<int,float>,type_pair<double,string>>.
*/ */
template<typename... LhsElements, typename... RhsElements> template<class ListA, class ListB,
struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...> > template<typename, typename> class Fun = to_type_pair>
struct tl_zip;
template<typename... LhsElements, typename... RhsElements,
template<typename, typename> class Fun>
struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...>, Fun>
{ {
typedef type_list<type_pair<LhsElements, RhsElements>...> type; static_assert(sizeof...(LhsElements) ==
private: sizeof...(RhsElements),
static_assert(type_list<LhsElements...>::size ==
type_list<RhsElements...>::size,
"Lists have different size"); "Lists have different size");
typedef type_list<typename Fun<LhsElements, RhsElements>::type...> type;
}; };
// static list list::zip_with_index(list) template<class ListA>
struct tl_unzip;
template<typename... Elements>
struct tl_unzip< type_list<Elements...> >
{
typedef type_list<typename Elements::first...> first;
typedef type_list<typename Elements::second...> second;
};
// static list zip_with_index(list)
template<bool Done, class List, size_t Pos, size_t...> template<bool Done, class List, size_t Pos, size_t...>
struct tl_zip_with_index_impl; struct tl_zip_with_index_impl;
...@@ -154,7 +165,7 @@ struct tl_zip_with_index<type_list<> > ...@@ -154,7 +165,7 @@ struct tl_zip_with_index<type_list<> >
typedef type_list<> type; typedef type_list<> type;
}; };
// list list::reverse() // list reverse()
template<class From, typename... Elements> template<class From, typename... Elements>
struct tl_reverse_impl; struct tl_reverse_impl;
...@@ -180,7 +191,7 @@ struct tl_reverse ...@@ -180,7 +191,7 @@ struct tl_reverse
typedef typename tl_reverse_impl<List>::type type; typedef typename tl_reverse_impl<List>::type type;
}; };
// bool list::find(type) // bool find(list, type)
/** /**
* @brief Finds the first element of type @p What beginning at * @brief Finds the first element of type @p What beginning at
...@@ -229,7 +240,7 @@ struct tl_find_if ...@@ -229,7 +240,7 @@ 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 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;
...@@ -252,13 +263,61 @@ struct tl_first_n_impl<N, type_list<L0, L...>, T...> ...@@ -252,13 +263,61 @@ struct tl_first_n_impl<N, type_list<L0, L...>, T...>
template<class List, size_t N> template<class List, size_t N>
struct tl_first_n struct tl_first_n
{ {
static_assert(List::size >= N, "List::size < N");
typedef typename tl_first_n_impl<N, List>::type type; typedef typename tl_first_n_impl<N, List>::type type;
private: };
static_assert(N > 0, "N == 0");
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;
};
template<size_t TargetSize, size_t Size, typename L0, typename... L, typename... T>
struct tl_last_n_impl<TargetSize, Size, type_list<L0, L...>, T...>
{
typedef typename tl_last_n_impl<TargetSize, Size,
type_list<L...>, T..., L0>::type type;
};
/**
* @brief Creates a new list from the first @p N elements of @p List.
*/
template<class List, size_t N>
struct tl_last_n
{
static_assert(List::size >= N, "List::size < N"); static_assert(List::size >= N, "List::size < N");
typedef typename tl_last_n_impl<N, List::size, List>::type type;
};
template<class List>
struct tl_last_n<List, 0>
{
typedef type_list<> type;
}; };
// bool list::forall(predicate) // bool forall(predicate)
/** /**
* @brief Tests whether a predicate holds for all elements of a list. * @brief Tests whether a predicate holds for all elements of a list.
...@@ -267,8 +326,8 @@ template<class List, template<typename> class Predicate> ...@@ -267,8 +326,8 @@ template<class List, template<typename> class Predicate>
struct tl_forall struct tl_forall
{ {
static constexpr bool value = static constexpr bool value =
Predicate<typename List::head>::value Predicate<class List::head>::value
&& tl_forall<typename List::tail, Predicate>::value; && tl_forall<class List::tail, Predicate>::value;
}; };
template<template<typename> class Predicate> template<template<typename> class Predicate>
...@@ -284,8 +343,8 @@ template<class List, template<typename> class Predicate> ...@@ -284,8 +343,8 @@ template<class List, template<typename> class Predicate>
struct tl_exists struct tl_exists
{ {
static constexpr bool value = static constexpr bool value =
Predicate<typename List::head>::value Predicate<class List::head>::value
|| tl_exists<typename List::tail, Predicate>::value; || tl_exists<class List::tail, Predicate>::value;
}; };
template<template<typename> class Predicate> template<template<typename> class Predicate>
...@@ -295,7 +354,7 @@ struct tl_exists<type_list<>, Predicate> ...@@ -295,7 +354,7 @@ struct tl_exists<type_list<>, Predicate>
}; };
// size_t list::count(predicate) // size_t count(predicate)
/** /**
* @brief Counts the number of elements in the list which satisfy a predicate. * @brief Counts the number of elements in the list which satisfy a predicate.
...@@ -304,8 +363,8 @@ template<class List, template<typename> class Predicate> ...@@ -304,8 +363,8 @@ template<class List, template<typename> class Predicate>
struct tl_count struct tl_count
{ {
static constexpr size_t value = static constexpr size_t value =
(Predicate<typename List::head>::value ? 1 : 0) (Predicate<class List::head>::value ? 1 : 0)
+ tl_count<typename List::tail, Predicate>::value; + tl_count<class List::tail, Predicate>::value;
}; };
template<template<typename> class Predicate> template<template<typename> class Predicate>
...@@ -314,7 +373,7 @@ struct tl_count<type_list<>, Predicate> ...@@ -314,7 +373,7 @@ struct tl_count<type_list<>, Predicate>
static constexpr size_t value = 0; static constexpr size_t value = 0;
}; };
// size_t list::count_not(predicate) // size_t count_not(predicate)
/** /**
* @brief Counts the number of elements in the list which satisfy a predicate. * @brief Counts the number of elements in the list which satisfy a predicate.
...@@ -323,8 +382,8 @@ template<class List, template<typename> class Predicate> ...@@ -323,8 +382,8 @@ template<class List, template<typename> class Predicate>
struct tl_count_not struct tl_count_not
{ {
static constexpr size_t value = static constexpr size_t value =
(Predicate<typename List::head>::value ? 0 : 1) (Predicate<class List::head>::value ? 0 : 1)
+ tl_count_not<typename List::tail, Predicate>::value; + tl_count_not<class List::tail, Predicate>::value;
}; };
template<template<typename> class Predicate> template<template<typename> class Predicate>
...@@ -333,7 +392,7 @@ struct tl_count_not<type_list<>, Predicate> ...@@ -333,7 +392,7 @@ struct tl_count_not<type_list<>, Predicate>
static constexpr size_t value = 0; static constexpr size_t value = 0;
}; };
// bool list::zipped_forall(predicate) // bool zipped_forall(predicate)
/** /**
* @brief Tests whether a predicate holds for all elements of a zipped list. * @brief Tests whether a predicate holds for all elements of a zipped list.
...@@ -353,23 +412,45 @@ struct tl_zipped_forall<type_list<>, Predicate> ...@@ -353,23 +412,45 @@ struct tl_zipped_forall<type_list<>, Predicate>
static constexpr bool value = true; static constexpr bool value = true;
}; };
// static list list::concat(list, list) template<class ListA, class ListB>
struct tl_concat_impl;
template<typename ListA, typename ListB>
struct tl_concat;
/** /**
* @brief Concatenates two lists. * @brief Concatenates two lists.
*/ */
template<typename... ListATypes, typename... ListBTypes> template<typename... ListATypes, typename... ListBTypes>
struct tl_concat<type_list<ListATypes...>, type_list<ListBTypes...> > struct tl_concat_impl<type_list<ListATypes...>, type_list<ListBTypes...> >
{ {
typedef type_list<ListATypes..., ListBTypes...> type; typedef type_list<ListATypes..., ListBTypes...> type;
}; };
// list list::push_back(list, type) // static list concat(list, list)
template<typename List, typename What> /**
* @brief Concatenates lists.
*/
template<class... Lists>
struct tl_concat;
template<class List0>
struct tl_concat<List0>
{
typedef List0 type;
};
template<class List0, class List1, class... Lists>
struct tl_concat<List0, List1, Lists...>
{
typedef typename tl_concat<
typename tl_concat_impl<List0, List1>::type,
Lists...
>::type
type;
};
// list push_back(list, type)
template<class List, typename What>
struct tl_push_back; struct tl_push_back;
/** /**
...@@ -381,37 +462,49 @@ struct tl_push_back<type_list<ListTypes...>, What> ...@@ -381,37 +462,49 @@ struct tl_push_back<type_list<ListTypes...>, What>
typedef type_list<ListTypes..., What> type; typedef type_list<ListTypes..., What> type;
}; };
// list list::appy(trait) template<class List, typename What>
struct tl_push_front;
/**
* @brief Appends @p What to given list.
*/
template<typename... ListTypes, typename What>
struct tl_push_front<type_list<ListTypes...>, What>
{
typedef type_list<What, ListTypes...> type;
};
template<typename List, template<typename> class Trait> // list map(list, trait)
struct tl_apply;
/** /**
* @brief Applies a "template function" to each element in the list. * @brief Creates a new list by applying a "template function" to each element.
*/ */
template<template<typename> class Trait, typename... Elements> template<class List, template<typename> class Fun>
struct tl_apply<type_list<Elements...>, Trait> struct tl_map;
template<template<typename> class Fun, typename... Elements>
struct tl_map<type_list<Elements...>, Fun>
{ {
typedef type_list<typename Trait<Elements>::type...> type; typedef type_list<typename Fun<Elements>::type...> type;
}; };
// list list::zipped_apply(trait) // list zipped_map(trait)
template<typename List, template<typename, typename> class Trait> template<class List, template<typename, typename> class Fun>
struct tl_zipped_apply; struct tl_zipped_map;
/** /**
* @brief Applies a "binary template function" to each element * @brief Creates a new list by applying a "binary template function"
* in the zipped list. * to each element.
*/ */
template<template<typename, typename> class Trait, typename... T> template<typename... T, template<typename, typename> class Fun>
struct tl_zipped_apply<type_list<T...>, Trait> struct tl_zipped_map<type_list<T...>, Fun>
{ {
typedef type_list<typename Trait<typename T::first, typedef type_list<typename Fun<typename T::first,
typename T::second>::type...> type; typename T::second>::type...> type;
}; };
// list list::pop_back() // list pop_back()
/** /**
* @brief Creates a new list wih all but the last element of @p List. * @brief Creates a new list wih all but the last element of @p List.
...@@ -423,7 +516,7 @@ struct tl_pop_back ...@@ -423,7 +516,7 @@ struct tl_pop_back
typedef typename tl_reverse<typename rlist::tail>::type type; typedef typename tl_reverse<typename rlist::tail>::type type;
}; };
// type list::at(size_t) // type at(size_t)
template<size_t N, typename... E> template<size_t N, typename... E>
struct tl_at_impl; struct tl_at_impl;
...@@ -454,7 +547,7 @@ struct tl_at<type_list<E...>, N> ...@@ -454,7 +547,7 @@ struct tl_at<type_list<E...>, N>
typedef typename tl_at_impl<N, E...>::type type; typedef typename tl_at_impl<N, E...>::type type;
}; };
// list list::prepend(type) // list prepend(type)
template<class List, typename What> template<class List, typename What>
struct tl_prepend; struct tl_prepend;
...@@ -469,8 +562,8 @@ struct tl_prepend<type_list<T...>, What> ...@@ -469,8 +562,8 @@ struct tl_prepend<type_list<T...>, What>
}; };
// list list::filter(predicate) // list filter(predicate)
// list list::filter_not(predicate) // list filter_not(predicate)
template<class List, bool... Selected> template<class List, bool... Selected>
struct tl_filter_impl; struct tl_filter_impl;
...@@ -526,7 +619,7 @@ struct tl_filter_not<type_list<T...>, Predicate> ...@@ -526,7 +619,7 @@ struct tl_filter_not<type_list<T...>, Predicate>
/** /**
* @brief Creates a new list containing all elements which * @brief Creates a new list containing all elements which
* are not equal to @p Type. * are equal to @p Type.
*/ */
template<class List, class Type> template<class List, class Type>
struct tl_filter_type; struct tl_filter_type;
...@@ -537,7 +630,20 @@ struct tl_filter_type<type_list<T...>, Type> ...@@ -537,7 +630,20 @@ struct tl_filter_type<type_list<T...>, Type>
typedef typename tl_filter_impl<type_list<T...>, std::is_same<T, Type>::value...>::type type; typedef typename tl_filter_impl<type_list<T...>, std::is_same<T, Type>::value...>::type type;
}; };
// list list::distinct(list) /**
* @brief Creates a new list containing all elements which
* are not equal to @p Type.
*/
template<class List, class Type>
struct tl_filter_not_type;
template<class Type, typename... T>
struct tl_filter_not_type<type_list<T...>, Type>
{
typedef typename tl_filter_impl<type_list<T...>, (!std::is_same<T, Type>::value)...>::type type;
};
// list distinct(list)
/** /**
* @brief Creates a new list from @p List without any duplicate elements. * @brief Creates a new list from @p List without any duplicate elements.
...@@ -560,28 +666,28 @@ struct tl_distinct<type_list<Head, Tail...> > ...@@ -560,28 +666,28 @@ struct tl_distinct<type_list<Head, Tail...> >
type; type;
}; };
// list list::resize(list, size, fill_type) // list resize(list, size, fill_type)
template<class List, bool OldSizeLessNewSize, template<class List, bool OldSizeLessNewSize,
size_t OldSize, size_t NewSize, typename FillType> size_t OldSize, size_t NewSize, typename FillType>
struct tl_resize_impl; 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_resize_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_first_n<List, NewSize>::type type;
}; };
template<class List, size_t Size, typename FillType> template<class List, size_t Size, typename FillType>
struct tl_resize_impl<List, false, Size, Size, FillType> struct tl_pad_right_impl<List, false, Size, Size, FillType>
{ {
typedef List type; typedef List type;
}; };
template<class List, size_t OldSize, size_t NewSize, typename FillType> template<class List, size_t OldSize, size_t NewSize, typename FillType>
struct tl_resize_impl<List, true, OldSize, NewSize, FillType> struct tl_pad_right_impl<List, true, OldSize, NewSize, FillType>
{ {
typedef typename tl_resize_impl< typedef typename tl_pad_right_impl<
typename tl_push_back<List, FillType>::type, typename tl_push_back<List, FillType>::type,
(OldSize + 1) < NewSize, (OldSize + 1) < NewSize,
OldSize + 1, OldSize + 1,
...@@ -596,14 +702,50 @@ struct tl_resize_impl<List, true, OldSize, NewSize, FillType> ...@@ -596,14 +702,50 @@ struct tl_resize_impl<List, true, OldSize, NewSize, FillType>
* @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>
struct tl_resize struct tl_pad_right
{ {
typedef typename tl_resize_impl< typedef typename tl_pad_right_impl<
List, (List::size < NewSize), List::size, NewSize, FillType List, (List::size < NewSize), List::size, NewSize, FillType
>::type >::type
type; type;
}; };
// bool pad_left(list, N)
template<class List, size_t OldSize, size_t NewSize, typename FillType>
struct tl_pad_left_impl
{
typedef typename tl_pad_left_impl<
typename tl_push_front<List, FillType>::type,
OldSize + 1,
NewSize,
FillType
>::type
type;
};
template<class List, size_t Size, typename FillType>
struct tl_pad_left_impl<List, Size, Size, FillType>
{
typedef List type;
};
/**
* @brief Resizes the list to contain @p NewSize elements and uses
* @p FillType to initialize prepended elements with.
*/
template<class List, size_t NewSize, typename FillType = void_type>
struct tl_pad_left
{
static_assert(NewSize >= List::size, "List too big");
typedef typename tl_pad_left_impl<
List, List::size, NewSize, FillType
>::type
type;
};
// bool is_zipped(list)
template<class List> template<class List>
struct tl_is_zipped struct tl_is_zipped
{ {
...@@ -617,7 +759,7 @@ template<class List, typename What> ...@@ -617,7 +759,7 @@ template<class List, typename What>
struct tl_trim struct tl_trim
{ {
typedef typename util::if_else< typedef typename util::if_else<
std::is_same<typename List::back, What>, std::is_same<class List::back, What>,
typename tl_trim<typename tl_pop_back<List>::type, What>::type, typename tl_trim<typename tl_pop_back<List>::type, What>::type,
util::wrapped<List> util::wrapped<List>
>::type >::type
...@@ -630,7 +772,7 @@ struct tl_trim<type_list<>, What> ...@@ -630,7 +772,7 @@ struct tl_trim<type_list<>, What>
typedef type_list<> type; typedef type_list<> type;
}; };
// list list::group_by(list, predicate) // list group_by(list, predicate)
template<bool Append, typename What, class Where> template<bool Append, typename What, class Where>
struct tl_group_by_impl_step; struct tl_group_by_impl_step;
......
...@@ -44,6 +44,12 @@ struct type_pair ...@@ -44,6 +44,12 @@ struct type_pair
typedef Second second; typedef Second second;
}; };
template<typename First, typename Second>
struct to_type_pair
{
typedef type_pair<First, Second> type;
};
template<class What> template<class What>
struct is_type_pair struct is_type_pair
{ {
......
...@@ -55,4 +55,9 @@ void const* abstract_tuple::native_data() const ...@@ -55,4 +55,9 @@ void const* abstract_tuple::native_data() const
return nullptr; return nullptr;
} }
void* abstract_tuple::mutable_native_data()
{
return nullptr;
}
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -103,8 +103,9 @@ if (!(line_of_code)) \ ...@@ -103,8 +103,9 @@ if (!(line_of_code)) \
#endif #endif
#define CPPA_ERROR(err_msg) \ #define CPPA_ERROR(err_msg) \
std::cerr << err_msg << std::endl; \ std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \
++cppa_ts.error_count << ": " << err_msg << std::endl; \
++cppa_ts.error_count
#define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc))) #define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc)))
......
...@@ -15,8 +15,11 @@ ...@@ -15,8 +15,11 @@
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
#include "cppa/util/rm_option.hpp"
#include "cppa/detail/invokable.hpp" #include "cppa/detail/invokable.hpp"
#include "cppa/detail/types_array.hpp" #include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp" #include "cppa/detail/object_array.hpp"
...@@ -28,135 +31,143 @@ using std::endl; ...@@ -28,135 +31,143 @@ using std::endl;
using namespace cppa; using namespace cppa;
template<class Expr, class Guard, typename Result, typename... Args> template<typename ArgType, typename Transformer>
class tpartial_function struct cf_transformed_type
{ {
typedef typename util::get_callable_trait<Transformer>::result_type result;
typedef typename util::rm_option<result>::type type;
};
bool collect(detail::tdata<>&) { return true; } template<typename ArgType>
struct cf_transformed_type<ArgType, util::void_type>
template<typename TData, typename T0, typename... Ts> {
bool collect(TData& td, T0 const& arg0, Ts const&... args) typedef ge_reference_wrapper<ArgType> type;
{
td.head = arg0;
return collect(td.tail(), args...);
}
public:
tpartial_function(Guard&& g, Expr&& e)
: m_guard(std::move(g)), m_expr(std::move(e))
{
}
tpartial_function(tpartial_function&& other)
: m_guard(std::move(other.m_guard))
, m_expr(std::move(other.m_expr))
{
}
tpartial_function(tpartial_function const&) = default;
bool defined_at(Args const&... args)
{
return m_guard(args...);
}
Result operator()(Args const&... args)
{
if (collect(m_args, args...)) return m_expr(args...);
throw std::logic_error("oops");
}
private:
typedef util::type_list<ge_reference_wrapper<Args>...> TransformedArgs;
typename detail::tdata_from_type_list<TransformedArgs>::type m_args;
Guard m_guard;
Expr m_expr;
}; };
template<typename T> template<typename ArgType>
T const& fw(T const& value) { return value; } struct cf_transformed_type<ArgType&, util::void_type>
{
typedef ge_mutable_reference_wrapper<ArgType> type;
};
template<typename T> template<typename ArgType>
struct rm_option struct cf_transformed_type<ArgType const&, util::void_type>
{ {
typedef T type; typedef ge_reference_wrapper<ArgType> type;
}; };
template<typename T> template<typename T>
struct rm_option<option<T> > struct cf_unwrap
{ {
typedef T type; typedef T type;
}; };
template<typename ArgType, typename Transformer> template<typename T>
struct cf_transformed_type struct cf_unwrap<ge_reference_wrapper<T> >
{ {
typedef typename util::get_callable_trait<Transformer>::result_type result; typedef T const& type;
typedef typename rm_option<result>::type type;
}; };
template<typename ArgType> template<typename T>
struct cf_transformed_type<ArgType, util::void_type> struct cf_unwrap<ge_mutable_reference_wrapper<T> >
{ {
typedef ge_reference_wrapper<ArgType> type; typedef T& type;
}; };
template<typename AbstractTuple>
struct invoke_policy_helper struct invoke_policy_helper
{ {
size_t i; size_t i;
detail::abstract_tuple const& tup; AbstractTuple& tup;
invoke_policy_helper(detail::abstract_tuple const& 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_reference_wrapper<T>& storage)
{ {
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<wildcard_position, class ArgsList> template<typename T>
struct gref_wrapped
{
typedef ge_reference_wrapper<T> type;
};
template<typename T>
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; struct invoke_policy;
template<typename... Args> template<class Pattern>
struct invoke_policy<wildcard_position::nil, util::type_list<Args...> > struct invoke_policy<wildcard_position::nil, Pattern>
{ {
template<typename Target> typedef Pattern filtered_pattern;
static bool invoke_args(Target& target, Args const&... args) 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;
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, true>,
Target& target, Ts&&... args)
{ {
return target(args...); return target(std::forward<Ts>(args)...);
} }
template<typename Target, typename... WrongArgs> template<typename Target, typename... Ts>
static bool invoke_args(Target&, WrongArgs const&...) static bool _invoke_args(std::integral_constant<bool, false>,
Target&, Ts&&...)
{ {
return false; return false;
} }
template<typename Target> template<typename Target, typename... Ts>
static bool invoke(Target& target, static bool invoke(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>
token;
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,
std::type_info const& arg_types, std::type_info const& arg_types,
detail::tuple_impl_info timpl, detail::tuple_impl_info timpl,
void const* native_arg, NativeArg native_arg,
detail::abstract_tuple const& tup) AbstractTuple& tup)
{ {
if (arg_types == typeid(util::type_list<Args...>)) if (arg_types == typeid(filtered_pattern))
{ {
if (native_arg) if (native_arg)
{ {
auto arg = reinterpret_cast<detail::tdata<Args...> const*>(native_arg); auto arg = reinterpret_cast<typename PolicyToken::native_type>(native_arg);
return util::unchecked_apply_tuple<bool>(target, *arg); return util::unchecked_apply_tuple<bool>(target, *arg);
} }
// 'fall through' // 'fall through'
} }
else if (timpl == detail::dynamically_typed) else if (timpl == detail::dynamically_typed)
{ {
auto& arr = detail::static_types_array<Args...>::arr; auto& arr = arr_type::arr;
if (tup.size() != sizeof...(Args)) if (tup.size() != filtered_pattern::size)
{ {
return false; return false;
} }
for (size_t i = 0; i < sizeof...(Args); ++i) for (size_t i = 0; i < filtered_pattern::size; ++i)
{ {
if (arr[i] != tup.type_at(i)) if (arr[i] != tup.type_at(i))
{ {
...@@ -170,64 +181,193 @@ struct invoke_policy<wildcard_position::nil, util::type_list<Args...> > ...@@ -170,64 +181,193 @@ struct invoke_policy<wildcard_position::nil, util::type_list<Args...> >
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
detail::tdata<ge_reference_wrapper<Args>...> ttup; typename PolicyToken::wrapped_refs ttup;
invoke_policy_helper iph{tup}; invoke_policy_helper<AbstractTuple> iph{tup};
util::static_foreach<0, sizeof...(Args)>::_ref(ttup, iph); util::static_foreach<0, filtered_pattern::size>::_ref(ttup, iph);
return util::apply_tuple(target, ttup); //return util::apply_tuple(target, ttup);
typename PolicyToken::wrapped_refs_fwd 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)
{
typedef typename detail::tdata_from_type_list<
typename util::tl_map<
filtered_pattern,
gref_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)
{
typedef typename detail::tdata_from_type_list<
typename util::tl_map<
filtered_pattern,
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);
} }
}; };
template<class Transformers, class Args> template<class PartialFun>
class apply_policy struct projection_helper
{ {
PartialFun const& fun;
projection_helper(PartialFun const& pfun) : fun(pfun) { }
template<typename... Args>
bool operator()(Args&&... args) const
{
if (fun.defined_at(std::forward<Args>(args)...))
{
fun(std::forward<Args>(args)...);
return true;
}
return false;
}
};
template<typename T>
struct add_const_ref
{
typedef T const& type;
};
/**
* @brief Projection implemented by a set of functors.
*/
template<class Pattern, class TargetSignature, class ProjectionFuns>
class projection
{
typedef typename detail::tdata_from_type_list<ProjectionFuns>::type
fun_container;
fun_container m_funs;
public: public:
template<typename... Ts> typedef Pattern pattern_type;
apply_policy(Ts&&... args) : m_transformer(std::forward<Ts>(args)...) { }
apply_policy(apply_policy&&) = default; typedef typename util::tl_filter_not_type<
apply_policy(apply_policy const&) = default; pattern_type,
anything
>::type
filtered_pattern_type;
template<class Guard, class Expr, typename... Ts> static_assert(ProjectionFuns::size <= filtered_pattern_type::size,
bool operator()(Guard& guard, Expr& expr, Ts const&... args) const "invalid projection (too many functions)");
{
typename detail::tdata_from_type_list< typedef TargetSignature arg_types;
typename util::tl_zipped_apply<
// fill arg_types with first arguments of const-references
// deduced from filtered_pattern_type
typedef typename util::tl_zipped_map<
typename util::tl_zip< typename util::tl_zip<
Args, typename util::tl_pad_left<
typename util::tl_resize< arg_types,
Transformers, filtered_pattern_type::size,
Args::size,
util::void_type util::void_type
>::type,
typename util::tl_map<
filtered_pattern_type,
add_const_ref
>::type >::type
>::type, >::type,
cf_transformed_type util::left_or_right
>::type
filled_arg_types;
// get a container that manages const and non-const references
typedef typename util::tl_zipped_map<
typename util::tl_zip<
filled_arg_types,
typename util::tl_pad_right<
ProjectionFuns,
filtered_pattern_type::size,
util::void_type
>::type >::type
>::type,
cf_transformed_type
>::type >::type
m_args; projection_map;
if (collect(m_args, m_transformer, args...))
typedef typename util::tl_map<projection_map, cf_unwrap>::type
projected_arg_types;
typedef typename detail::tdata_from_type_list<projection_map>::type
collected_arg_types;
projection(fun_container const& args) : m_funs(args)
{ {
if (util::unchecked_apply_tuple<bool>(guard, m_args)) }
projection(projection const&) = default;
template<class PartialFun, typename... Args>
bool _arg_impl(std::integral_constant<bool, true>,
PartialFun& fun, Args&&... args ) const
{ {
util::apply_tuple(expr, m_args); collected_arg_types pargs;
return true; 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; return false;
} }
/**
* @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
> token;
return _arg_impl(token, fun, std::forward<Args>(args)...);
}
private: private:
template<class Storage, typename T> template<class Storage, typename T>
static inline bool fetch_(Storage& storage, T const& value) static inline bool fetch_(Storage& storage, T&& value)
{ {
storage = value; storage = std::forward<T>(value);
return true; return true;
} }
template<class Result> template<class Storage>
static inline bool fetch_(Result& storage, option<Result>&& value) static inline bool fetch_(Storage& storage, option<Storage>&& value)
{ {
if (value) if (value)
{ {
...@@ -238,267 +378,325 @@ class apply_policy ...@@ -238,267 +378,325 @@ class apply_policy
} }
template<class Storage, typename Fun, typename T> template<class Storage, typename Fun, typename T>
static inline bool fetch(Storage& storage, Fun const& fun, T const& arg) static inline bool fetch(Storage& storage, Fun const& fun, T&& arg)
{ {
return fetch_(storage, fun(arg)); return fetch_(storage, fun(std::forward<T>(arg)));
} }
template<typename T> template<typename Storage, typename T>
static inline bool fetch(ge_reference_wrapper<T>& storage, static inline bool fetch(Storage& storage,
util::void_type const&, util::void_type const&,
T const& arg) T&& value)
{ {
storage = arg; storage = std::forward<T>(value);
return true; return true;
} }
static inline bool collect(detail::tdata<>&, detail::tdata<> const&) { return true; } static inline bool collect(detail::tdata<>&, detail::tdata<> const&)
{
return true;
}
template<class TData, typename T0, typename... Ts> template<class TData, typename T0, typename... Ts>
static inline bool collect(TData& td, detail::tdata<> const&, T0 const& arg0, Ts const&... args) static inline bool collect(TData& td, detail::tdata<> const&,
T0&& arg0, Ts&&... args)
{ {
td.set(arg0, args...); td.set(std::forward<T0>(arg0), std::forward<Ts>(args)...);
return true; 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, T0 const& arg0, Ts const&... args) static inline bool collect(TData& td, Trans const& tr,
T0&& arg0, Ts&&... args)
{ {
return fetch(td.head, tr.head, arg0) return fetch(td.head, tr.head, std::forward<T0>(arg0))
&& collect(td.tail(), tr.tail(), args...); && collect(td.tail(), tr.tail(), std::forward<Ts>(args)...);
} }
typename detail::tdata_from_type_list<Transformers>::type m_transformer;
}; };
template<typename Expr, size_t ExprArgs, size_t NumArgs> template<class Pattern, class TargetSignature>
struct apply_args class projection<Pattern, TargetSignature, util::type_list<> >
{ {
template<typename Arg0, typename... Args>
static inline void _(Expr& expr, Arg0 const&, Args const&... args)
{
apply_args<Expr, ExprArgs, NumArgs-1>::_(expr, args...);
}
};
template<typename Expr, size_t Num> public:
struct apply_args<Expr, Num, Num>
{
template<typename... Args>
static inline void _(Expr& expr, Args const&... args)
{
expr(args...);
}
};
template<class Args> typedef Pattern pattern_type;
class apply_policy<util::type_list<>, Args>
{
public: typedef typename util::tl_filter_not_type<
pattern_type,
anything
>::type
filtered_pattern_type;
apply_policy(detail::tdata<> const&) { } typedef filtered_pattern_type projected_arg_types;
apply_policy() = default; projection(detail::tdata<>) { }
apply_policy(apply_policy const&) = default; projection(projection&&) = default;
projection(projection const&) = default;
template<class Guard, class Expr, typename... Ts> template<class PartialFun, typename... Args>
bool operator()(Guard& guard, Expr& expr, Ts const&... args) const bool operator()(PartialFun& fun, Args&&... args) const
{ {
if (guard(args...)) projection_helper<PartialFun> helper{fun};
{ return helper(std::forward<Args>(args)...);
typedef typename util::get_callable_trait<Expr>::type ctrait;
apply_args<Expr, ctrait::arg_types::size, sizeof...(Ts)>::_(expr, args...);
return true;
}
return false;
} }
}; };
struct invoke_helper template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl
{ {
template<class Leaf> typedef typename util::get_callable_trait<Expr>::type ctrait;
bool operator()(Leaf const& leaf, typedef typename util::tl_filter_not_type<Pattern, anything>::type argl;
std::type_info const& v0, typedef projection<Pattern, typename ctrait::arg_types, Transformers> type1;
detail::tuple_impl_info v1, typedef typename get_tpartial_function<
void const* v2, Expr,
detail::abstract_tuple const& v3) const Guard,
{ typename type1::projected_arg_types
typedef typename Leaf::args_list alist; >::type
typedef invoke_policy<get_wildcard_position<alist>(), alist> impl; type2;
return impl::invoke(leaf, v0, v1, v2, v3); typedef std::pair<type1, type2> type;
}
template<class Leaf, typename... Args>
bool operator()(Leaf const& leaf,
Args const&... args) const
{
typedef typename Leaf::args_list alist;
typedef invoke_policy<get_wildcard_position<alist>(), alist> impl;
return impl::invoke_args(leaf, args...);
}
}; };
template<class Expr, class Guard, class Transformers, class ArgTypes> template<typename First, typename Second>
class conditional_fun_leaf; struct pjf_same_pattern
: std::is_same<typename First::second::first_type::pattern_type,
typename Second::second::first_type::pattern_type>
{
};
template<class Expr, class Guard, class Transformers, typename... Args> // last invocation step; evaluates a {projection, tpartial_function} pair
class conditional_fun_leaf<Expr, Guard, Transformers, util::type_list<Args...> > template<typename Data>
struct invoke_helper3
{ {
Data const& data;
invoke_helper3(Data const& mdata) : data(mdata) { }
template<size_t Pos, typename T, typename... Args>
inline bool operator()(util::type_pair<std::integral_constant<size_t, Pos>, T>,
Args&&... args) const
{
auto const& target = get<Pos>(data);
return target.first(target.second, std::forward<Args>(args)...);
//return (get<Pos>(data))(args...);
}
};
public: template<class Data, class Token, class Pattern>
struct invoke_helper2
{
typedef Pattern pattern_type;
typedef typename util::tl_filter_not_type<pattern_type, anything>::type arg_types;
Data const& data;
invoke_helper2(Data const& mdata) : data(mdata) { }
template<typename... Args>
bool invoke(Args&&... args) const
{
typedef invoke_policy<get_wildcard_position<Pattern>(), Pattern> impl;
return impl::invoke(*this, std::forward<Args>(args)...);
typedef util::type_list<Args...> args_list;
template<typename G, typename E, typename... TFuns> // resolve arguments;
conditional_fun_leaf(G&& g, E&& e, TFuns&&... tfuns) // helper4 encapsulates forwarding of (args...) to invoke_policy which
: m_apply(std::forward<TFuns>(tfuns)...) // calls operator()() of this object with resolved args
, m_guard(std::forward<G>(g)), m_expr(std::forward<E>(e)) //invoke_helper4 fun;
// return fun(*this, std::forward<Args>(args)...);
}
// resolved argument list (called from invoke_policy)
template<typename... Args>
bool operator()(Args&&... args) const
{ {
Token token;
invoke_helper3<Data> fun{data};
return util::static_foreach<0, Token::size>::eval_or(token, fun, std::forward<Args>(args)...);
} }
};
conditional_fun_leaf(conditional_fun_leaf const&) = default; // invokes a group of {projection, tpartial_function} pairs
template<typename Data>
bool operator()(Args const&... args) const struct invoke_helper
{
Data const& data;
invoke_helper(Data const& mdata) : data(mdata) { }
// token: type_list<type_pair<integral_constant<size_t, X>,
// std::pair<projection, tpartial_function>>,
// ...>
// all {projection, tpartial_function} pairs have the same pattern
// thus, can be invoked from same data
template<class Token, typename... Args>
bool operator()(Token, Args&&... args) const
{ {
return m_apply(m_guard, m_expr, args...); typedef typename Token::head type_pair;
typedef typename type_pair::second leaf_pair;
typedef typename leaf_pair::first_type projection_type;
// next invocation step
invoke_helper2<Data,
Token,
typename projection_type::pattern_type> fun{data};
return fun.invoke(std::forward<Args>(args)...);
} }
private:
typedef typename util::tl_trim<Transformers, util::void_type>::type trimmed;
apply_policy<trimmed, args_list> m_apply;
Guard m_guard;
Expr m_expr;
}; };
template<class ArgTypes, class Expr, class Guard, typename... TFuns> template<typename T>
struct cfl_ struct pjf_fwd_
{ {
typedef conditional_fun_leaf<Expr, Guard, static inline T const& _(T const& arg) { return arg; }
util::type_list<TFuns...>, ArgTypes> static inline T const& _(T&& arg) { return arg; }
type; static inline T& _(T& arg) { return arg; }
}; };
template<class ArgTypes, class LeavesTData, class... LeafImpl> template<typename T>
struct cfh_ struct pjf_fwd
: pjf_fwd_<
typename detail::implicit_conversions<
typename util::rm_ref<T>::type
>::type>
{ {
typedef LeavesTData leaves_type; // tdata<tdata...> };
typedef typename leaves_type::back_type back_leaf; // tdata
// manipulate leaves type to push back leaf_impl
typedef typename util::tl_pop_back<typename leaves_type::types>::type
prefix;
// type_list<tdata...>
typedef typename detail::tdata_from_type_list< template<typename T>
typename util::tl_concat< struct is_manipulator_leaf;
typename back_leaf::types,
util::type_list<LeafImpl...>
>::type
>::type
suffix; // tdata
typedef typename util::tl_push_back<prefix, suffix>::type template<typename First, typename Second>
concatenated; // type_list<tdata...> struct is_manipulator_leaf<std::pair<First, Second> >
{
static constexpr bool value = Second::manipulates_args;
};
typedef typename detail::tdata_from_type_list<concatenated>::type type; 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);
}
}; };
namespace cppa { namespace detail { 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);
}
};
template<class Lhs, class Rhs> void collect_tdata(detail::tdata<>&)
struct tdata_concatenate; {
}
template<class... Lhs, class... Rhs> template<typename Storage, typename... Args>
struct tdata_concatenate<tdata<Lhs...>, tdata<Rhs...> > void collect_tdata(Storage& storage, detail::tdata<> const&, Args const&... args)
{ {
typedef tdata<Lhs..., Rhs...> type; collect_tdata(storage, args...);
}; }
} } // namespace cppa::detail template<typename Storage, typename Arg0, typename... Args>
void collect_tdata(Storage& storage, Arg0 const& arg0, Args const&... args)
{
storage = arg0.head;
collect_tdata(storage.tail(), arg0.tail(), args...);
}
/**
* @brief A function that works on the projection of given data rather than
* on the data itself.
*/
template<class... Leaves> template<class... Leaves>
class conditional_fun class projected_fun
{ {
public: public:
typedef util::type_list<Leaves...> leaves_list;
typedef typename util::tl_zip_with_index<leaves_list>::type zipped_list;
typedef typename util::tl_group_by<zipped_list, pjf_same_pattern>::type
eval_order;
static constexpr bool has_manipulator =
util::tl_exists<leaves_list, is_manipulator_leaf>::value;
template<typename... Args> template<typename... Args>
conditional_fun(Args&&... args) : m_leaves(std::forward<Args>(args)...) projected_fun(Args&&... args) : m_leaves(std::forward<Args>(args)...)
{ {
} }
conditional_fun(conditional_fun&& other) : m_leaves(std::move(other.m_leaves)) projected_fun(projected_fun&& other) : m_leaves(std::move(other.m_leaves))
{ {
} }
conditional_fun(conditional_fun const&) = default; projected_fun(projected_fun const&) = default;
//conditional_fun& operator=(conditional_fun&&) = default; bool invoke(any_tuple const& tup) const
//conditional_fun& operator=(conditional_fun const&) = default;
typedef void const* const_void_ptr;
bool invoke(std::type_info const& arg_types,
detail::tuple_impl_info timpl,
const_void_ptr native_arg,
detail::abstract_tuple const& tup) const
{ {
invoke_helper fun; return pjf_invoke<has_manipulator, eval_order>
return util::static_foreach<0, sizeof...(Leaves)>::eval_or(m_leaves, fun, arg_types, timpl, native_arg, tup); ::_(m_leaves, tup);
} }
bool invoke(any_tuple const& tup) const bool invoke(any_tuple& tup) const
{ {
auto const& cvals = *(tup.cvals()); return pjf_invoke<has_manipulator, eval_order>
return invoke(*(cvals.type_token()), ::_(m_leaves, tup);
cvals.impl_type(),
cvals.native_data(),
cvals);
} }
template<typename... Args> bool invoke(any_tuple&& tup) const
bool operator()(Args const&... args)
{ {
invoke_helper fun; any_tuple tmp{tup};
return util::static_foreach<0, sizeof...(Leaves)>::eval_or(m_leaves, fun, args...); return invoke(tmp);
} }
/* template<typename... Args>
template<typename OtherLeaves> bool invoke_args(Args&&... args) const
conditional_fun<typename detail::tdata_concatenate<Leaves, OtherLeaves>::type>
or_else(conditional_fun<OtherLeaves> const& other) const
{ {
return {m_leaves, other.m_leaves}; eval_order token;
invoke_helper<decltype(m_leaves)> fun{m_leaves};
return util::static_foreach<0, eval_order::size>
::eval_or(token, fun, std::forward<Args>(args)...);
} }
*/
template<class... Rhs> template<typename... Args>
conditional_fun<Leaves..., Rhs...> bool operator()(Args&&... args) const
or_else(conditional_fun<Rhs...> const& other) const
{ {
return {m_leaves, other.m_leaves}; // applies implicit conversions and passes rvalues as const lvalue refs
return invoke_args(pjf_fwd<Args>::_(args)...);
} }
/* template<class... Rhs>
template<class... LeafImpl, class Others0, class... Others> projected_fun<Leaves..., Rhs...>
conditional_fun< or_else(projected_fun<Rhs...> const& other) const
typename detail::tdata_concatenate<
typename cfh_<back_arg_types, Leaves, LeafImpl...>::type,
detail::tdata<Others0, Others...>
>::type>
or_else(conditional_fun<detail::tdata<detail::tdata<back_arg_types, LeafImpl...>, Others0, Others...>> const& other) const
{ {
typedef conditional_fun<detail::tdata<detail::tdata<back_arg_types, LeafImpl...>>> detail::tdata<ge_reference_wrapper<Leaves>...,
head_fun; ge_reference_wrapper<Rhs>... > all_leaves;
typedef conditional_fun<detail::tdata<Others0, Others...>> tail_fun; collect_tdata(all_leaves, m_leaves, other.m_leaves);
return or_else(head_fun{other.m_leaves.head}) return {all_leaves};
.or_else(tail_fun{other.m_leaves.tail()});
} }
*/
//private: //private:
...@@ -509,82 +707,199 @@ class conditional_fun ...@@ -509,82 +707,199 @@ class conditional_fun
}; };
template<class ArgTypes, class Expr, class Guard, typename... TFuns> template<class List>
conditional_fun<typename cfl_<ArgTypes, Expr, Guard, TFuns...>::type> struct projected_fun_from_type_list;
cfun(Expr e, Guard g, TFuns... tfs)
template<typename... Args>
struct projected_fun_from_type_list<util::type_list<Args...> >
{
typedef projected_fun<Args...> type;
};
template<typename... Lhs, typename... Rhs>
projected_fun<Lhs..., Rhs...> operator,(projected_fun<Lhs...> const& lhs,
projected_fun<Rhs...> const& rhs)
{
return lhs.or_else(rhs);
}
template<typename Arg0, typename... Args>
typename projected_fun_from_type_list<
typename util::tl_concat<
typename Arg0::leaves_list,
typename Args::leaves_list...
>::type
>::type
pj_concat(Arg0 const& arg0, Args const&... args)
{ {
typedef typename cfl_<ArgTypes, Expr, Guard, TFuns...>::type leaf_type; typename detail::tdata_from_type_list<
typedef typename util::get_callable_trait<Expr>::arg_types expr_args; typename util::tl_map<
static_assert(ArgTypes::size >= expr_args::size, typename util::tl_concat<
"Functor has too many arguments"); typename Arg0::leaves_list,
return leaf_type{std::move(g), std::move(e), std::move(tfs)...}; typename Args::leaves_list...
>::type,
gref_wrapped
>::type
>::type
all_leaves;
collect_tdata(all_leaves, arg0.m_leaves, args.m_leaves...);
return {all_leaves};
} }
#define VERBOSE(LineOfCode) cout << #LineOfCode << " = " << (LineOfCode) << endl #define VERBOSE(LineOfCode) cout << #LineOfCode << " = " << (LineOfCode) << endl
float tofloat(int i) { return i; } template<typename... Args>
any_tuple make_any_tuple(Args&&... args)
{
return make_cow_tuple(std::forward<Args>(args)...);
}
template<bool IsFun, typename T>
struct vg_fwd_
{
static inline T const& _(T const& arg) { return arg; }
static inline T&& _(T&& arg) { return std::move(arg); }
static inline T& _(T& arg) { return arg; }
};
template<typename T>
struct vg_fwd_<true, T>
{
template<typename Arg>
static inline util::void_type _(Arg&&) { return {}; }
};
// absorbs functors
template<typename T>
struct vg_fwd
: vg_fwd_<util::is_callable<typename util::rm_ref<T>::type>::value,
typename util::rm_ref<T>::type>
{
};
struct dummy_guard template<typename FilteredPattern>
class value_guard
{ {
typename detail::tdata_from_type_list<FilteredPattern>::type m_args;
template<typename... Args> template<typename... Args>
inline bool operator()(Args const&...) const inline bool _eval(util::void_type const&,
detail::tdata<> const&, Args&&...) const
{ {
return true; return true;
} }
template<class Tail, typename Arg0, typename... Args>
inline bool _eval(util::void_type const&, Tail const& tail,
Arg0 const&, Args const&... args ) const
{
return _eval(tail.head, tail.tail(), args...);
}
template<typename Head, class Tail, typename Arg0, typename... Args>
inline bool _eval(Head const& head, Tail const& tail,
Arg0 const& arg0, Args const&... args) const
{
return head == arg0 && _eval(tail.head, tail.tail(), args...);
}
public:
value_guard() = default;
value_guard(value_guard const&) = default;
template<typename... Args>
value_guard(Args const&... args) : m_args(vg_fwd<Args>::_(args)...)
{
}
template<typename... Args>
inline bool operator()(Args const&... args) const
{
return _eval(m_args.head, m_args.tail(), args...);
}
}; };
template<typename... Args> typedef value_guard< util::type_list<> > dummy_guard;
any_tuple make_any_tuple(Args&&... args)
{
return make_cow_tuple(std::forward<Args>(args)...);
}
struct from_args { }; struct cf_builder_from_args { };
template<class Guard, class Transformers, class Pattern> template<class Guard, class Transformers, class Pattern>
struct cf_builder struct cf_builder
{ {
typedef typename detail::tdata_from_type_list<Transformers>::type
fun_container;
Guard m_guard; Guard m_guard;
typename detail::tdata_from_type_list<Transformers>::type m_funs; typename detail::tdata_from_type_list<Transformers>::type m_funs;
public: public:
cf_builder() = default;
template<typename... Args> template<typename... Args>
cf_builder(from_args const&, Args const&... args) : m_guard(args...), m_funs(args...) cf_builder(cf_builder_from_args const&, Args const&... args)
: m_guard(args...)
, m_funs(args...)
{ {
} }
template<typename G> cf_builder(Guard& mg, fun_container const& funs)
cf_builder(G&& g) : m_guard(std::forward<G>(g)) : m_guard(std::move(mg)), m_funs(funs)
{ {
} }
template<typename G, typename F> cf_builder(Guard const& mg, fun_container const& funs)
cf_builder(G&& g, F&& f) : m_guard(std::forward<G>(g)), m_funs(std::forward<F>(f)) : m_guard(mg), m_funs(funs)
{ {
} }
template<typename NewGuard> template<typename NewGuard>
cf_builder<NewGuard, Transformers, Pattern> when(NewGuard ng) cf_builder<
guard_expr<
logical_and_op,
guard_expr<exec_xfun_op, Guard, util::void_type>,
NewGuard>,
Transformers,
Pattern>
when(NewGuard ng,
typename util::disable_if_c<
std::is_same<NewGuard, NewGuard>::value
&& std::is_same<Guard, dummy_guard>::value
>::type* = 0 ) const
{
return {(gcall(m_guard) && ng), m_funs};
}
template<typename NewGuard>
cf_builder<NewGuard, Transformers, Pattern>
when(NewGuard ng,
typename util::enable_if_c<
std::is_same<NewGuard, NewGuard>::value
&& std::is_same<Guard, dummy_guard>::value
>::type* = 0 ) const
{ {
return {ng, m_funs}; return {ng, m_funs};
} }
template<typename Expr> template<typename Expr>
conditional_fun<conditional_fun_leaf<Expr, Guard, Transformers, Pattern> > projected_fun<typename get_cfl<Expr, Guard, Transformers, Pattern>::type>
operator>>(Expr expr) const operator>>(Expr expr) const
{ {
typedef conditional_fun_leaf<Expr, Guard, Transformers, Pattern> tfun; typedef typename get_cfl<Expr, Guard, Transformers, Pattern>::type tpair;
return tfun{m_guard, std::move(expr), m_funs}; return tpair{typename tpair::first_type{m_funs},
typename tpair::second_type{std::move(expr), m_guard}};
} }
}; };
template<typename... T> template<typename... T>
cf_builder<dummy_guard, util::type_list<>, util::type_list<T...> > _on() cf_builder<value_guard<util::type_list<> >,
util::type_list<>,
util::type_list<T...> > _on()
{ {
return {dummy_guard{}}; return {};
} }
template<bool IsFun, typename T> template<bool IsFun, typename T>
...@@ -626,44 +941,6 @@ struct boxed_and_callable_to_void : to_void_impl<detail::is_boxed<T>::value || u ...@@ -626,44 +941,6 @@ struct boxed_and_callable_to_void : to_void_impl<detail::is_boxed<T>::value || u
{ {
}; };
template<typename Pattern>
class value_guard;
template<typename... Types>
class value_guard<util::type_list<Types...> >
{
detail::tdata<Types...> m_args;
inline bool _eval(util::void_type const&, detail::tdata<> const&) const
{
return true;
}
template<class Tail, typename Arg0, typename... Args>
inline bool _eval(util::void_type const&, Tail const& tail,
Arg0 const&, Args const&... args) const
{
return _eval(tail.head, tail.tail(), args...);
}
template<typename Head, class Tail, typename Arg0, typename... Args>
inline bool _eval(Head const& head, Tail const& tail,
Arg0 const& arg0, Args const&... args) const
{
return head == arg0 && _eval(tail.head, tail.tail(), args...);
}
public:
template<typename... Args>
value_guard(Args const&... args) : m_args(args...) { }
inline bool operator()(Types const&... args) const
{
return _eval(m_args.head, m_args.tail(), args...);
}
};
template<bool IsCallable, typename T> template<bool IsCallable, typename T>
struct pattern_type_ struct pattern_type_
{ {
...@@ -676,7 +953,7 @@ struct pattern_type_ ...@@ -676,7 +953,7 @@ struct pattern_type_
template<typename T> template<typename T>
struct pattern_type_<false, T> struct pattern_type_<false, T>
{ {
typedef typename util::rm_ref<T>::type type; typedef typename util::rm_ref<typename detail::unboxed<T>::type>::type type;
}; };
template<typename T> template<typename T>
...@@ -686,13 +963,24 @@ struct pattern_type : pattern_type_<util::is_callable<T>::value && !detail::is_b ...@@ -686,13 +963,24 @@ struct pattern_type : pattern_type_<util::is_callable<T>::value && !detail::is_b
template<typename Arg0, typename... Args> template<typename Arg0, typename... Args>
cf_builder< cf_builder<
value_guard<typename util::tl_apply<util::type_list<Arg0, Args...>, boxed_and_callable_to_void>::type>, value_guard<
typename util::tl_apply<util::type_list<Arg0, Args...>, not_callable_to_void>::type, typename util::tl_trim<
typename util::tl_map<
util::type_list<Arg0, Args...>,
boxed_and_callable_to_void
>::type,
util::void_type
>::type
>,
typename util::tl_map<
util::type_list<Arg0, Args...>,
not_callable_to_void
>::type,
util::type_list<typename pattern_type<Arg0>::type, util::type_list<typename pattern_type<Arg0>::type,
typename pattern_type<Args>::type...> > typename pattern_type<Args>::type...> >
_on(Arg0 const& arg0, Args const&... args) _on(Arg0 const& arg0, Args const&... args)
{ {
return {from_args{}, arg0, args...}; return {cf_builder_from_args{}, arg0, args...};
} }
std::string int2str(int i) std::string int2str(int i)
...@@ -702,8 +990,12 @@ std::string int2str(int i) ...@@ -702,8 +990,12 @@ std::string int2str(int i)
option<int> str2int(std::string const& str) option<int> str2int(std::string const& str)
{ {
if (str == "42") return 42; char* endptr = nullptr;
if (str == "41") return 41; int result = static_cast<int>(strtol(str.c_str(), &endptr, 10));
if (endptr != nullptr && *endptr == '\0')
{
return result;
}
return {}; return {};
} }
...@@ -739,6 +1031,16 @@ struct is_same_ : std::is_same<typename First::second, typename Second::second> ...@@ -739,6 +1031,16 @@ struct is_same_ : std::is_same<typename First::second, typename Second::second>
{ {
}; };
#define CPPA_CHECK_INVOKED(FunName, Args) \
if ( ( FunName Args ) == false || invoked != #FunName ) { \
CPPA_ERROR("invocation of " #FunName " failed"); \
} invoked = ""
#define CPPA_CHECK_NOT_INVOKED(FunName, Args) \
if ( ( FunName Args ) == true || invoked == #FunName ) { \
CPPA_ERROR(#FunName " erroneously invoked"); \
} invoked = ""
size_t test__tuple() size_t test__tuple()
{ {
CPPA_TEST(test__tuple); CPPA_TEST(test__tuple);
...@@ -755,30 +1057,133 @@ size_t test__tuple() ...@@ -755,30 +1057,133 @@ size_t test__tuple()
static_assert(std::is_same<zz3, zz9>::value, "group_by failed"); static_assert(std::is_same<zz3, zz9>::value, "group_by failed");
cout << detail::demangle(typeid(zz3).name()) << endl;
typedef util::type_list<int, int> token1; typedef util::type_list<int, int> token1;
typedef util::type_list<float> token2; typedef util::type_list<float> token2;
//auto f00 = cfun<token1>([](int, int) { cout << "f0[1]!" << endl; }, _x1 > _x2) std::string invoked;
// .or_else(cfun<token1>([](int, int) { cout << "f0[2]!" << endl; }, _x1 == 2 && _x2 == 2))
// .or_else(cfun<token2>([](float) { cout << "f0[3]!" << endl; }, dummy_guard{})); auto f00 = _on<int, int>() >> [&]() { invoked = "f00"; };
CPPA_CHECK_INVOKED(f00, (42, 42));
auto f00 = _on<int, int>() >> []() { };
auto f01 = _on<int, int>().when(_x1 == 42) >> []() { }; auto f01 = _on<int, int>().when(_x1 == 42) >> [&]() { invoked = "f01"; };
auto f02 = _on<int, int>().when(_x1 == 42 && _x2 * 2 == _x1) >> []() { }; CPPA_CHECK_INVOKED(f01, (42, 42));
CPPA_CHECK_NOT_INVOKED(f01, (1, 2));
auto f03 = _on(42, val<int>) >> [](int) { };
auto f02 = _on<int, int>().when(_x1 == 42 && _x2 * 2 == _x1) >> [&]() { invoked = "f02"; };
auto f04 = _on(42, int2str).when(_x2 == "42") >> []() { }; CPPA_CHECK_NOT_INVOKED(f02, (0, 0));
auto f05 = _on(42, str2int).when(_x2 % 2 == 0) >> []() { }; CPPA_CHECK_NOT_INVOKED(f02, (42, 42));
CPPA_CHECK_NOT_INVOKED(f02, (2, 1));
CPPA_CHECK_INVOKED(f02, (42, 21));
CPPA_CHECK(f02.invoke(make_any_tuple(42, 21)));
CPPA_CHECK_EQUAL("f02", invoked);
invoked = "";
auto f03 = _on(42, val<int>) >> [&](int a, int) { invoked = "f03"; CPPA_CHECK_EQUAL(42, a); };
CPPA_CHECK_NOT_INVOKED(f03, (0, 0));
CPPA_CHECK_INVOKED(f03, (42, 42));
auto f04 = _on(42, int2str).when(_x2 == "42") >> [&]() { invoked = "f04"; };
CPPA_CHECK_NOT_INVOKED(f04, (0, 0));
CPPA_CHECK_NOT_INVOKED(f04, (0, 42));
CPPA_CHECK_NOT_INVOKED(f04, (42, 0));
CPPA_CHECK_INVOKED(f04, (42, 42));
auto f05 = _on(str2int).when(_x1 % 2 == 0) >> [&]() { invoked = "f05"; };
CPPA_CHECK_NOT_INVOKED(f05, ("1"));
CPPA_CHECK_INVOKED(f05, ("2"));
auto f06 = _on(42, str2int).when(_x2 % 2 == 0) >> [&]() { invoked = "f06"; };
CPPA_CHECK_NOT_INVOKED(f06, (0, "0"));
CPPA_CHECK_NOT_INVOKED(f06, (42, "1"));
CPPA_CHECK_INVOKED(f06, (42, "2"));
int f07_val = 1;
auto f07 = _on<int>().when(_x1 == gref(f07_val)) >> [&]() { invoked = "f07"; };
CPPA_CHECK_NOT_INVOKED(f07, (0));
CPPA_CHECK_INVOKED(f07, (1));
CPPA_CHECK_NOT_INVOKED(f07, (2));
++f07_val;
CPPA_CHECK_NOT_INVOKED(f07, (0));
CPPA_CHECK_NOT_INVOKED(f07, (1));
CPPA_CHECK_INVOKED(f07, (2));
int f08_val = 666;
auto f08 = _on<int>() >> [&](int& mref) { mref = 8; invoked = "f08"; };
CPPA_CHECK_INVOKED(f08, (f08_val));
CPPA_CHECK_EQUAL(8, f08_val);
any_tuple f08_any_val = make_any_tuple(666);
CPPA_CHECK(f08.invoke(f08_any_val));
CPPA_CHECK_EQUAL(8, f08_any_val.get_as<int>(0));
int f09_val = 666;
auto f09 = _on(str2int, val<int>) >> [&](int& mref) { mref = 9; invoked = "f09"; };
CPPA_CHECK_NOT_INVOKED(f09, ("hello lambda", f09_val));
CPPA_CHECK_INVOKED(f09, ("0", f09_val));
CPPA_CHECK_EQUAL(9, f09_val);
any_tuple f09_any_val = make_any_tuple("0", 666);
CPPA_CHECK(f09.invoke(f09_any_val));
CPPA_CHECK_EQUAL(9, f09_any_val.get_as<int>(1));
f09_any_val.get_as_mutable<int>(1) = 666;
any_tuple f09_any_val_copy{f09_any_val};
CPPA_CHECK_EQUAL(f09_any_val.at(0), f09_any_val_copy.at(0));
// detaches f09_any_val from f09_any_val_copy
CPPA_CHECK(f09.invoke(f09_any_val));
CPPA_CHECK_EQUAL(9, f09_any_val.get_as<int>(1));
CPPA_CHECK_EQUAL(666, f09_any_val_copy.get_as<int>(1));
// no longer the same data
CPPA_CHECK_NOT_EQUAL(f09_any_val.at(0), f09_any_val_copy.at(0));
auto f10 =
(
_on<int>().when(_x1 < 10) >> [&]() { invoked = "f10.0"; },
_on<int>() >> [&]() { invoked = "f10.1"; }
);
CPPA_CHECK(f10(9));
CPPA_CHECK_EQUAL("f10.0", invoked);
CPPA_CHECK(f10(10));
CPPA_CHECK_EQUAL("f10.1", invoked);
int f11_fun = 0;
auto f11 = pj_concat
(
_on<int>().when(_x1 == 1) >> [&]() { f11_fun = 1; },
_on<int>().when(_x1 == 2) >> [&]() { f11_fun = 2; },
_on<int>().when(_x1 == 3) >> [&]() { f11_fun = 3; },
_on<int>().when(_x1 == 4) >> [&]() { f11_fun = 4; },
_on<int>().when(_x1 == 5) >> [&]() { f11_fun = 5; },
_on<int>().when(_x1 == 6) >> [&]() { f11_fun = 6; },
_on<int>().when(_x1 == 7) >> [&]() { f11_fun = 7; },
_on<int>().when(_x1 == 8) >> [&]() { f11_fun = 8; },
_on<int>().when(_x1 >= 9) >> [&]() { f11_fun = 9; },
_on(str2int) >> [&]() { f11_fun = 10; },
_on<std::string>() >> [&]() { f11_fun = 11; }
);
CPPA_CHECK(f11(1));
CPPA_CHECK_EQUAL(1, f11_fun);
CPPA_CHECK(f11(3));
CPPA_CHECK_EQUAL(3, f11_fun);
CPPA_CHECK(f11(8));
CPPA_CHECK_EQUAL(8, f11_fun);
CPPA_CHECK(f11(10));
CPPA_CHECK_EQUAL(9, f11_fun);
CPPA_CHECK(f11("hello lambda"));
CPPA_CHECK_EQUAL(11, f11_fun);
CPPA_CHECK(f11("10"));
CPPA_CHECK_EQUAL(10, f11_fun);
/*
VERBOSE(f00(42, 42)); VERBOSE(f00(42, 42));
VERBOSE(f01(42, 42)); VERBOSE(f01(42, 42));
VERBOSE(f02(42, 42)); VERBOSE(f02(42, 42));
VERBOSE(f02(42, 21)); VERBOSE(f02(42, 21));
VERBOSE(f03(42, 42)); VERBOSE(f03(42, 42));
cout << detail::demangle(typeid(f04).name()) << endl;
VERBOSE(f04(42, 42)); VERBOSE(f04(42, 42));
VERBOSE(f04(42, std::string("42"))); VERBOSE(f04(42, std::string("42")));
...@@ -787,7 +1192,19 @@ size_t test__tuple() ...@@ -787,7 +1192,19 @@ size_t test__tuple()
VERBOSE(f05(42, std::string("42"))); VERBOSE(f05(42, std::string("42")));
VERBOSE(f05(42, std::string("hello world!"))); VERBOSE(f05(42, std::string("hello world!")));
exit(0); auto f06 = f04.or_else(_on<int, int>().when(_x2 > _x1) >> []() { });
VERBOSE(f06(42, 42));
VERBOSE(f06(1, 2));
*/
/*
auto f06 = _on<anything, int>() >> []() { };
VERBOSE(f06(1));
VERBOSE(f06(1.f, 2));
*/
/*
auto f0 = cfun<token1>([](int, int) { cout << "f0[0]!" << endl; }, _x1 < _x2) auto f0 = cfun<token1>([](int, int) { cout << "f0[0]!" << endl; }, _x1 < _x2)
//.or_else(f00) //.or_else(f00)
...@@ -827,8 +1244,7 @@ size_t test__tuple() ...@@ -827,8 +1244,7 @@ size_t test__tuple()
VERBOSE(f0.invoke(*dt1.cvals()->type_token(), dt1.cvals()->impl_type(), dt1.cvals()->native_data(), *dt1.cvals())); VERBOSE(f0.invoke(*dt1.cvals()->type_token(), dt1.cvals()->impl_type(), dt1.cvals()->native_data(), *dt1.cvals()));
VERBOSE(f1.invoke(*dt1.cvals()->type_token(), dt1.cvals()->impl_type(), dt1.cvals()->native_data(), *dt1.cvals())); VERBOSE(f1.invoke(*dt1.cvals()->type_token(), dt1.cvals()->impl_type(), dt1.cvals()->native_data(), *dt1.cvals()));
exit(0); */
// check type correctness of make_cow_tuple() // check type correctness of make_cow_tuple()
auto t0 = make_cow_tuple("1", 2); auto t0 = make_cow_tuple("1", 2);
......
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