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; }
}; };
/** /**
......
This diff is collapsed.
...@@ -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)))
......
This diff is collapsed.
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