Commit 8f393dc7 authored by neverlord's avatar neverlord

pattern matching

parent 7ee5a950
......@@ -173,10 +173,12 @@ nobase_library_include_HEADERS = \
cppa/serializer.hpp \
cppa/stacked_event_based_actor.hpp \
cppa/to_string.hpp \
cppa/tpartial_function.hpp \
cppa/tuple_cast.hpp \
cppa/type_value_pair.hpp \
cppa/uniform_type_info.hpp \
cppa/util/abstract_uniform_type_info.hpp \
cppa/util/apply_args.hpp \
cppa/util/apply_tuple.hpp \
cppa/util/arg_match_t.hpp \
cppa/util/at.hpp \
......@@ -201,11 +203,13 @@ nobase_library_include_HEADERS = \
cppa/util/is_manipulator.hpp \
cppa/util/is_mutable_ref.hpp \
cppa/util/is_primitive.hpp \
cppa/util/left_or_right.hpp \
cppa/util/producer_consumer_list.hpp \
cppa/util/pt_dispatch.hpp \
cppa/util/pt_token.hpp \
cppa/util/replace_type.hpp \
cppa/util/ripemd_160.hpp \
cppa/util/rm_option.hpp \
cppa/util/rm_ref.hpp \
cppa/util/shared_lock_guard.hpp \
cppa/util/shared_spinlock.hpp \
......
......@@ -258,3 +258,7 @@ cppa/detail/matches.hpp
unit_testing/test__match.cpp
cppa/guard_expr.hpp
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
return any_tuple{simple_view(std::forward<T>(value), token)};
}
void force_detach()
{
m_vals.detach();
}
void reset();
private:
......
......@@ -89,6 +89,11 @@ class cow_ptr
return *this;
}
void detach()
{
(void) detached_ptr();
}
inline void reset(T* value = nullptr) { m_ptr.reset(value); }
inline T* get() { return (m_ptr) ? detached_ptr() : nullptr; }
......
......@@ -61,6 +61,7 @@ class abstract_tuple : public ref_counted
// mutators
virtual void* mutable_at(size_t pos) = 0;
virtual void* mutable_native_data();
// accessors
virtual size_t size() const = 0;
......
......@@ -65,7 +65,7 @@ class ftor_behavior<true, true, F, Args...> : public scheduled_actor
F m_fun;
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
tdata_type;
......@@ -104,7 +104,7 @@ class ftor_behavior<false, true, F, Args...> : public scheduled_actor
F m_fun;
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
tdata_type;
......
......@@ -274,7 +274,7 @@ template<typename Fun, class Pattern>
struct select_invokable_impl
{
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;
static constexpr mapping_policy mp = get_mapping_policy<arg_types>();
typedef invokable_impl<Fun, pattern_policy<mp, Pattern> > type;
......@@ -284,7 +284,7 @@ template<typename Fun>
struct select_invokable_impl<Fun, pattern<anything> >
{
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;
typedef typename util::rm_ref<typename arg_types::head>::type arg0;
static_assert(arg_types::size < 2, "functor has too many arguments");
......
......@@ -43,6 +43,7 @@
#include "cppa/util/disable_if.hpp"
#include "cppa/util/arg_match_t.hpp"
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/implicit_conversions.hpp"
......@@ -65,6 +66,18 @@ inline void* ptr_to(T* what) { return what; }
template<typename T>
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"
*/
......@@ -82,16 +95,25 @@ struct tdata<>
typedef util::void_type back_type;
typedef util::type_list<> types;
static constexpr size_t tdata_size = 0;
static constexpr size_t num_elements = 0;
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&) { }
// swallow "arg_match" silently
constexpr tdata(util::wrapped<util::arg_match_t> const&) { }
//// swallow "arg_match" silently
//constexpr tdata(util::wrapped<util::arg_match_t> const&) { }
tdata<>& tail() { return *this; }
......@@ -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>
void tdata_set(tdata<X...>& rhs, tdata<Y...> const& lhs);
......@@ -126,7 +191,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
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 tdata<Tail...> tail_type;
......@@ -142,23 +207,31 @@ struct tdata<Head, Tail...> : tdata<Tail...>
//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
template<typename... Args>
tdata(Head const& v0, Args const&... vals) : super(vals...), head(v0) { }
//template<typename... Args>
//tdata(Head const& v0, Args const&... vals) : super(vals...), head(v0) { }
// allow partial initialization
template<typename... Args>
tdata(Head&& v0, Args const&... vals) : super(vals...), head(std::move(v0)) { }
//template<typename... Args>
//tdata(Head&& v0, Args const&... vals) : super(vals...), head(std::move(v0)) { }
// allow initialization with wrapped<Head> (uses the default constructor)
template<typename... Args>
tdata(util::wrapped<Head> const&, Args const&... vals)
: super(vals...), head()
// allow (partial) initialization from a different tdata
// with traling extra arguments to initialize additional arguments
template<typename... Y>
tdata(tdata<Y...>& other) : super(other.tail()), head(other.head)
{
}
// allow (partial) initialization from a different tdata
// with traling extra arguments to initialize additional arguments
template<typename... Y>
tdata(tdata<Y...> const& other) : super(other.tail()), head(other.head)
{
......@@ -170,6 +243,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
{
}
/*
template<typename... Y>
tdata(Head const& arg, tdata<Y...> const& other)
: super(other), head(arg)
......@@ -203,14 +277,7 @@ struct tdata<Head, Tail...> : tdata<Tail...>
: 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>
tdata& operator=(tdata<Y...> const& other)
......
......@@ -73,6 +73,11 @@ class tuple_vals : public abstract_tuple
return &m_data;
}
void* mutable_native_data()
{
return &m_data;
}
inline data_type& data()
{
return m_data;
......
......@@ -46,11 +46,11 @@ template<typename...> class cow_tuple;
// forward declaration of get(detail::tdata<...> const&)
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&)
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<...>&)
template<size_t N, typename... Tn>
......@@ -60,6 +60,13 @@ typename util::at<N, Tn...>::type& get_ref(detail::tdata<Tn...>&);
template<size_t N, typename... 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
#endif // GET_HPP
......@@ -37,8 +37,12 @@
#include <functional>
#include <type_traits>
#include "cppa/config.hpp"
#include "cppa/util/at.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/enable_if.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/detail/tdata.hpp"
......@@ -54,6 +58,8 @@ enum operator_id
logical_and_op, logical_or_op,
// pseudo operators for function invocation
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
dummy_op
};
......@@ -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};
}
/**
* @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
{
bool sc;
......@@ -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>
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(ge_reference_wrapper const&) = default;
ge_reference_wrapper& operator=(ge_reference_wrapper const&) = default;
T const& get() const { return *value; }
operator T const& () const { return *value; }
T const& get() const { CPPA_REQUIRE(value != 0); return *value; }
operator T const& () const { CPPA_REQUIRE(value != 0); return *value; }
};
// support use of gref(BooleanVariable) as receive loop 'guard'
......@@ -352,11 +381,11 @@ struct ge_unbound<ge_reference_wrapper<T>, Tuple>
// unbound type of placeholder
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),
"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
......@@ -435,6 +464,12 @@ struct ge_result_<guard_expr<OP, First, Second>, Tuple>
*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>
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)
template<class Tuple, int 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>
......@@ -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>
struct ge_eval_<exec_fun1_op, Tuple, First, Second>
{
......@@ -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>
auto ge_invoke(guard_expr<OP, First, Second> const& ge,
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);
}
......@@ -630,7 +675,7 @@ struct ge_invoke_helper
GuardExpr const& ge;
ge_invoke_helper(GuardExpr const& arg) : ge(arg) { }
template<typename... Args>
bool operator()(Args&&... args)
bool operator()(Args&&... args) const
{
return ge_invoke(ge, std::forward<Args>(args)...);
}
......
......@@ -117,7 +117,7 @@ class rvalue_builder
typedef typename get_callable_trait<F>::type ctrait;
typedef typename ctrait::arg_types raw_arg_types;
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 pattern_from_type_list<full_types>::type epattern;
return get_invokable_impl<epattern>(std::forward<F>(f),
......@@ -231,7 +231,7 @@ class on_the_fly_rvalue_builder
typedef typename get_callable_trait<F>::type ctrait;
typedef typename ctrait::arg_types raw_types;
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;
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>
struct apply_tuple_impl
{
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)...);
}
......@@ -53,7 +53,7 @@ template<typename Result, size_t... Range>
struct apply_tuple_impl<Result, true, Range...>
{
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)...);
}
......@@ -75,7 +75,7 @@ template<typename Result, bool IsManipulator>
struct apply_tuple_util<Result, IsManipulator, 1, 0>
{
template<typename F, class Unused>
static Result apply(F&& f, Unused const&)
static Result apply(F& f, Unused const&)
{
return f();
}
......@@ -119,6 +119,14 @@ Result unchecked_apply_tuple_in_range(F&& fun, Tuple<T...> const& 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
// does not evaluate result type of functor
template<typename Result, typename F,
......@@ -129,6 +137,16 @@ Result unchecked_apply_tuple(F&& fun, Tuple<T...> const& 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
#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>
struct static_foreach_impl
{
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...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>::_(c, f, args...);
f(get<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_(c, f, std::forward<Args>(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...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>::_ref(c, f, args...);
f(get_ref<Begin>(c), std::forward<Args>(args)...);
static_foreach_impl<(Begin+1 < End), Begin+1, End>
::_ref(c, f, std::forward<Args>(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...)
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>::eval(c, f, args...);
return f(get<Begin>(c), std::forward<Args>(args)...)
&& static_foreach_impl<(Begin+1 < End), Begin+1, End>
::eval(c, f, std::forward<Args>(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...)
|| static_foreach_impl<(Begin+1 < End), Begin+1, End>::eval_or(c, f, args...);
return f(get<Begin>(c), std::forward<Args>(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>
struct static_foreach_impl<false, X, Y>
{
template<typename... Args>
static inline void _(Args const&...) { }
static inline void _(Args&&...) { }
template<typename... Args>
static inline void _ref(Args const&...) { }
static inline void _ref(Args&&...) { }
template<typename... Args>
static inline bool eval(Args const&...) { return true; }
static inline bool eval(Args&&...) { return true; }
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...> >
static constexpr bool value = true;
};
// static list list::zip(list, list)
template<class ListA, class ListB>
struct tl_zip;
// static list zip(list, list)
/**
* @brief Zips two lists of equal size.
......@@ -113,17 +110,31 @@ struct tl_zip;
* e.g., tl_zip<type_list<int,double>,type_list<float,string>>::type
* is type_list<type_pair<int,float>,type_pair<double,string>>.
*/
template<typename... LhsElements, typename... RhsElements>
struct tl_zip<type_list<LhsElements...>, type_list<RhsElements...> >
template<class ListA, class ListB,
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;
private:
static_assert(type_list<LhsElements...>::size ==
type_list<RhsElements...>::size,
static_assert(sizeof...(LhsElements) ==
sizeof...(RhsElements),
"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...>
struct tl_zip_with_index_impl;
......@@ -154,7 +165,7 @@ struct tl_zip_with_index<type_list<> >
typedef type_list<> type;
};
// list list::reverse()
// list reverse()
template<class From, typename... Elements>
struct tl_reverse_impl;
......@@ -180,7 +191,7 @@ struct tl_reverse
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
......@@ -229,7 +240,7 @@ struct tl_find_if
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>
struct tl_first_n_impl;
......@@ -252,13 +263,61 @@ struct tl_first_n_impl<N, type_list<L0, L...>, T...>
template<class List, size_t N>
struct tl_first_n
{
static_assert(List::size >= N, "List::size < N");
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");
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.
......@@ -267,8 +326,8 @@ template<class List, template<typename> class Predicate>
struct tl_forall
{
static constexpr bool value =
Predicate<typename List::head>::value
&& tl_forall<typename List::tail, Predicate>::value;
Predicate<class List::head>::value
&& tl_forall<class List::tail, Predicate>::value;
};
template<template<typename> class Predicate>
......@@ -284,8 +343,8 @@ template<class List, template<typename> class Predicate>
struct tl_exists
{
static constexpr bool value =
Predicate<typename List::head>::value
|| tl_exists<typename List::tail, Predicate>::value;
Predicate<class List::head>::value
|| tl_exists<class List::tail, Predicate>::value;
};
template<template<typename> class 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.
......@@ -304,8 +363,8 @@ template<class List, template<typename> class Predicate>
struct tl_count
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 1 : 0)
+ tl_count<typename List::tail, Predicate>::value;
(Predicate<class List::head>::value ? 1 : 0)
+ tl_count<class List::tail, Predicate>::value;
};
template<template<typename> class Predicate>
......@@ -314,7 +373,7 @@ struct tl_count<type_list<>, Predicate>
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.
......@@ -323,8 +382,8 @@ template<class List, template<typename> class Predicate>
struct tl_count_not
{
static constexpr size_t value =
(Predicate<typename List::head>::value ? 0 : 1)
+ tl_count_not<typename List::tail, Predicate>::value;
(Predicate<class List::head>::value ? 0 : 1)
+ tl_count_not<class List::tail, Predicate>::value;
};
template<template<typename> class Predicate>
......@@ -333,7 +392,7 @@ struct tl_count_not<type_list<>, Predicate>
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.
......@@ -353,23 +412,45 @@ struct tl_zipped_forall<type_list<>, Predicate>
static constexpr bool value = true;
};
// static list list::concat(list, list)
template<typename ListA, typename ListB>
struct tl_concat;
template<class ListA, class ListB>
struct tl_concat_impl;
/**
* @brief Concatenates two lists.
*/
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;
};
// 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;
/**
......@@ -381,37 +462,49 @@ struct tl_push_back<type_list<ListTypes...>, What>
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>
struct tl_apply;
// list map(list, trait)
/**
* @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>
struct tl_apply<type_list<Elements...>, Trait>
template<class List, template<typename> class Fun>
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>
struct tl_zipped_apply;
template<class List, template<typename, typename> class Fun>
struct tl_zipped_map;
/**
* @brief Applies a "binary template function" to each element
* in the zipped list.
* @brief Creates a new list by applying a "binary template function"
* to each element.
*/
template<template<typename, typename> class Trait, typename... T>
struct tl_zipped_apply<type_list<T...>, Trait>
template<typename... T, template<typename, typename> class Fun>
struct tl_zipped_map<type_list<T...>, Fun>
{
typedef type_list<typename Trait<typename T::first,
typename T::second>::type...> type;
typedef type_list<typename Fun<typename T::first,
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.
......@@ -423,7 +516,7 @@ struct tl_pop_back
typedef typename tl_reverse<typename rlist::tail>::type type;
};
// type list::at(size_t)
// type at(size_t)
template<size_t N, typename... E>
struct tl_at_impl;
......@@ -454,7 +547,7 @@ struct tl_at<type_list<E...>, N>
typedef typename tl_at_impl<N, E...>::type type;
};
// list list::prepend(type)
// list prepend(type)
template<class List, typename What>
struct tl_prepend;
......@@ -469,8 +562,8 @@ struct tl_prepend<type_list<T...>, What>
};
// list list::filter(predicate)
// list list::filter_not(predicate)
// list filter(predicate)
// list filter_not(predicate)
template<class List, bool... Selected>
struct tl_filter_impl;
......@@ -526,7 +619,7 @@ struct tl_filter_not<type_list<T...>, Predicate>
/**
* @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>
struct tl_filter_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;
};
// 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.
......@@ -560,28 +666,28 @@ struct tl_distinct<type_list<Head, Tail...> >
type;
};
// list list::resize(list, size, fill_type)
// list resize(list, size, fill_type)
template<class List, bool OldSizeLessNewSize,
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>
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;
};
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;
};
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,
(OldSize + 1) < NewSize,
OldSize + 1,
......@@ -596,14 +702,50 @@ struct tl_resize_impl<List, true, OldSize, NewSize, FillType>
* @p FillType to initialize the new elements with.
*/
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
>::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>
struct tl_is_zipped
{
......@@ -617,7 +759,7 @@ template<class List, typename What>
struct tl_trim
{
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,
util::wrapped<List>
>::type
......@@ -630,7 +772,7 @@ struct tl_trim<type_list<>, What>
typedef type_list<> type;
};
// list list::group_by(list, predicate)
// list group_by(list, predicate)
template<bool Append, typename What, class Where>
struct tl_group_by_impl_step;
......
......@@ -44,6 +44,12 @@ struct type_pair
typedef Second second;
};
template<typename First, typename Second>
struct to_type_pair
{
typedef type_pair<First, Second> type;
};
template<class What>
struct is_type_pair
{
......
......@@ -55,4 +55,9 @@ void const* abstract_tuple::native_data() const
return nullptr;
}
void* abstract_tuple::mutable_native_data()
{
return nullptr;
}
} } // namespace cppa::detail
......@@ -103,8 +103,9 @@ if (!(line_of_code)) \
#endif
#define CPPA_ERROR(err_msg) \
std::cerr << err_msg << std::endl; \
++cppa_ts.error_count
std::cerr << "ERROR in file " << __FILE__ << " on line " << __LINE__ \
<< ": " << err_msg << std::endl; \
++cppa_ts.error_count
#define CPPA_CHECK_NOT_EQUAL(lhs_loc, rhs_loc) CPPA_CHECK(((lhs_loc) != (rhs_loc)))
......
......@@ -15,8 +15,11 @@
#include "cppa/to_string.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/intrusive_ptr.hpp"
#include "cppa/tpartial_function.hpp"
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/rm_option.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/object_array.hpp"
......@@ -28,135 +31,143 @@ using std::endl;
using namespace cppa;
template<class Expr, class Guard, typename Result, typename... Args>
class tpartial_function
template<typename ArgType, typename Transformer>
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 TData, typename T0, typename... Ts>
bool collect(TData& td, T0 const& arg0, Ts const&... args)
{
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 ArgType>
struct cf_transformed_type<ArgType, util::void_type>
{
typedef ge_reference_wrapper<ArgType> type;
};
template<typename T>
T const& fw(T const& value) { return value; }
template<typename ArgType>
struct cf_transformed_type<ArgType&, util::void_type>
{
typedef ge_mutable_reference_wrapper<ArgType> type;
};
template<typename T>
struct rm_option
template<typename ArgType>
struct cf_transformed_type<ArgType const&, util::void_type>
{
typedef T type;
typedef ge_reference_wrapper<ArgType> type;
};
template<typename T>
struct rm_option<option<T> >
struct cf_unwrap
{
typedef T type;
};
template<typename ArgType, typename Transformer>
struct cf_transformed_type
template<typename T>
struct cf_unwrap<ge_reference_wrapper<T> >
{
typedef typename util::get_callable_trait<Transformer>::result_type result;
typedef typename rm_option<result>::type type;
typedef T const& type;
};
template<typename ArgType>
struct cf_transformed_type<ArgType, util::void_type>
template<typename T>
struct cf_unwrap<ge_mutable_reference_wrapper<T> >
{
typedef ge_reference_wrapper<ArgType> type;
typedef T& type;
};
template<typename AbstractTuple>
struct invoke_policy_helper
{
size_t i;
detail::abstract_tuple const& tup;
invoke_policy_helper(detail::abstract_tuple const& tp) : i(0), tup(tp) { }
AbstractTuple& tup;
invoke_policy_helper(AbstractTuple& tp) : i(0), tup(tp) { }
template<typename T>
void operator()(ge_reference_wrapper<T>& storage)
{
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;
template<typename... Args>
struct invoke_policy<wildcard_position::nil, util::type_list<Args...> >
template<class Pattern>
struct invoke_policy<wildcard_position::nil, Pattern>
{
template<typename Target>
static bool invoke_args(Target& target, Args const&... args)
typedef Pattern filtered_pattern;
typedef typename detail::tdata_from_type_list<Pattern>::type native_data_type;
typedef typename detail::static_types_array_from_type_list<Pattern>::type arr_type;
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>
static bool invoke_args(Target&, WrongArgs const&...)
template<typename Target, typename... Ts>
static bool _invoke_args(std::integral_constant<bool, false>,
Target&, Ts&&...)
{
return false;
}
template<typename Target>
static bool invoke(Target& target,
std::type_info const& arg_types,
detail::tuple_impl_info timpl,
void const* native_arg,
detail::abstract_tuple const& tup)
template<typename Target, typename... Ts>
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,
detail::tuple_impl_info timpl,
NativeArg native_arg,
AbstractTuple& tup)
{
if (arg_types == typeid(util::type_list<Args...>))
if (arg_types == typeid(filtered_pattern))
{
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);
}
// 'fall through'
}
else if (timpl == detail::dynamically_typed)
{
auto& arr = detail::static_types_array<Args...>::arr;
if (tup.size() != sizeof...(Args))
auto& arr = arr_type::arr;
if (tup.size() != filtered_pattern::size)
{
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))
{
......@@ -170,64 +181,193 @@ struct invoke_policy<wildcard_position::nil, util::type_list<Args...> >
return false;
}
// either dynamically typed or statically typed but not a native tuple
detail::tdata<ge_reference_wrapper<Args>...> ttup;
invoke_policy_helper iph{tup};
util::static_foreach<0, sizeof...(Args)>::_ref(ttup, iph);
return util::apply_tuple(target, ttup);
typename PolicyToken::wrapped_refs ttup;
invoke_policy_helper<AbstractTuple> iph{tup};
util::static_foreach<0, filtered_pattern::size>::_ref(ttup, iph);
//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 PartialFun>
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;
};
template<class Transformers, class Args>
class apply_policy
/**
* @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:
template<typename... Ts>
apply_policy(Ts&&... args) : m_transformer(std::forward<Ts>(args)...) { }
typedef Pattern pattern_type;
typedef typename util::tl_filter_not_type<
pattern_type,
anything
>::type
filtered_pattern_type;
apply_policy(apply_policy&&) = default;
apply_policy(apply_policy const&) = default;
static_assert(ProjectionFuns::size <= filtered_pattern_type::size,
"invalid projection (too many functions)");
template<class Guard, class Expr, typename... Ts>
bool operator()(Guard& guard, Expr& expr, Ts const&... args) const
{
typename detail::tdata_from_type_list<
typename util::tl_zipped_apply<
typedef TargetSignature arg_types;
// fill arg_types with first arguments of const-references
// deduced from filtered_pattern_type
typedef typename util::tl_zipped_map<
typename util::tl_zip<
Args,
typename util::tl_resize<
Transformers,
Args::size,
typename util::tl_pad_left<
arg_types,
filtered_pattern_type::size,
util::void_type
>::type,
typename util::tl_map<
filtered_pattern_type,
add_const_ref
>::type
>::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,
cf_transformed_type
>::type
>::type
m_args;
if (collect(m_args, m_transformer, args...))
projection_map;
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)
{
}
projection(projection const&) = default;
template<class PartialFun, typename... Args>
bool _arg_impl(std::integral_constant<bool, true>,
PartialFun& fun, Args&&... args ) const
{
collected_arg_types pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...))
{
if (util::unchecked_apply_tuple<bool>(guard, m_args))
{
util::apply_tuple(expr, m_args);
return true;
}
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;
}
/**
* @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:
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;
}
template<class Result>
static inline bool fetch_(Result& storage, option<Result>&& value)
template<class Storage>
static inline bool fetch_(Storage& storage, option<Storage>&& value)
{
if (value)
{
......@@ -238,268 +378,326 @@ class apply_policy
}
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>
static inline bool fetch(ge_reference_wrapper<T>& storage,
util::void_type const&,
T const& arg)
template<typename Storage, typename T>
static inline bool fetch(Storage& storage,
util::void_type const&,
T&& value)
{
storage = arg;
storage = std::forward<T>(value);
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>
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;
}
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)
&& collect(td.tail(), tr.tail(), args...);
return fetch(td.head, tr.head, std::forward<T0>(arg0))
&& 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>
struct apply_args
template<class Pattern, class TargetSignature>
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>
struct apply_args<Expr, Num, Num>
{
template<typename... Args>
static inline void _(Expr& expr, Args const&... args)
{
expr(args...);
}
};
public:
template<class Args>
class apply_policy<util::type_list<>, Args>
{
typedef Pattern pattern_type;
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;
apply_policy(apply_policy const&) = default;
projection(detail::tdata<>) { }
projection(projection&&) = default;
projection(projection const&) = default;
template<class Guard, class Expr, typename... Ts>
bool operator()(Guard& guard, Expr& expr, Ts const&... args) const
template<class PartialFun, typename... Args>
bool operator()(PartialFun& fun, Args&&... args) const
{
if (guard(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;
projection_helper<PartialFun> helper{fun};
return helper(std::forward<Args>(args)...);
}
};
struct invoke_helper
template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl
{
template<class Leaf>
bool operator()(Leaf const& leaf,
std::type_info const& v0,
detail::tuple_impl_info v1,
void const* v2,
detail::abstract_tuple const& v3) const
{
typedef typename Leaf::args_list alist;
typedef invoke_policy<get_wildcard_position<alist>(), alist> impl;
return impl::invoke(leaf, v0, v1, v2, v3);
}
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...);
}
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename util::tl_filter_not_type<Pattern, anything>::type argl;
typedef projection<Pattern, typename ctrait::arg_types, Transformers> type1;
typedef typename get_tpartial_function<
Expr,
Guard,
typename type1::projected_arg_types
>::type
type2;
typedef std::pair<type1, type2> type;
};
template<class Expr, class Guard, class Transformers, class ArgTypes>
class conditional_fun_leaf;
template<typename First, typename Second>
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>
class conditional_fun_leaf<Expr, Guard, Transformers, util::type_list<Args...> >
// last invocation step; evaluates a {projection, tpartial_function} pair
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>
conditional_fun_leaf(G&& g, E&& e, TFuns&&... tfuns)
: m_apply(std::forward<TFuns>(tfuns)...)
, m_guard(std::forward<G>(g)), m_expr(std::forward<E>(e))
// resolve arguments;
// helper4 encapsulates forwarding of (args...) to invoke_policy which
// calls operator()() of this object with resolved args
//invoke_helper4 fun;
// return fun(*this, std::forward<Args>(args)...);
}
// resolved argument list (called from invoke_policy)
template<typename... Args>
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;
bool operator()(Args const&... args) const
// invokes a group of {projection, tpartial_function} pairs
template<typename Data>
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>
struct cfl_
template<typename T>
struct pjf_fwd_
{
typedef conditional_fun_leaf<Expr, Guard,
util::type_list<TFuns...>, ArgTypes>
type;
static inline T const& _(T const& arg) { return arg; }
static inline T const& _(T&& arg) { return arg; }
static inline T& _(T& arg) { return arg; }
};
template<class ArgTypes, class LeavesTData, class... LeafImpl>
struct cfh_
template<typename T>
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<
typename util::tl_concat<
typename back_leaf::types,
util::type_list<LeafImpl...>
>::type
>::type
suffix; // tdata
template<typename T>
struct is_manipulator_leaf;
typedef typename util::tl_push_back<prefix, suffix>::type
concatenated; // type_list<tdata...>
template<typename First, typename Second>
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>
struct tdata_concatenate;
void collect_tdata(detail::tdata<>&)
{
}
template<class... Lhs, class... Rhs>
struct tdata_concatenate<tdata<Lhs...>, tdata<Rhs...> >
template<typename Storage, typename... Args>
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>
class conditional_fun
class projected_fun
{
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>
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;
//conditional_fun& operator=(conditional_fun const&) = default;
typedef void const* const_void_ptr;
bool invoke(any_tuple const& tup) const
{
return pjf_invoke<has_manipulator, eval_order>
::_(m_leaves, tup);
}
bool invoke(std::type_info const& arg_types,
detail::tuple_impl_info timpl,
const_void_ptr native_arg,
detail::abstract_tuple const& tup) const
bool invoke(any_tuple& tup) const
{
invoke_helper fun;
return util::static_foreach<0, sizeof...(Leaves)>::eval_or(m_leaves, fun, arg_types, timpl, native_arg, tup);
return pjf_invoke<has_manipulator, eval_order>
::_(m_leaves, tup);
}
bool invoke(any_tuple const& tup) const
bool invoke(any_tuple&& tup) const
{
auto const& cvals = *(tup.cvals());
return invoke(*(cvals.type_token()),
cvals.impl_type(),
cvals.native_data(),
cvals);
any_tuple tmp{tup};
return invoke(tmp);
}
template<typename... Args>
bool operator()(Args const&... args)
bool invoke_args(Args&&... args) const
{
invoke_helper fun;
return util::static_foreach<0, sizeof...(Leaves)>::eval_or(m_leaves, fun, args...);
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<typename OtherLeaves>
conditional_fun<typename detail::tdata_concatenate<Leaves, OtherLeaves>::type>
or_else(conditional_fun<OtherLeaves> const& other) const
template<typename... Args>
bool operator()(Args&&... args) 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>
conditional_fun<Leaves..., Rhs...>
or_else(conditional_fun<Rhs...> const& other) const
projected_fun<Leaves..., Rhs...>
or_else(projected_fun<Rhs...> const& other) const
{
return {m_leaves, other.m_leaves};
detail::tdata<ge_reference_wrapper<Leaves>...,
ge_reference_wrapper<Rhs>... > all_leaves;
collect_tdata(all_leaves, m_leaves, other.m_leaves);
return {all_leaves};
}
/*
template<class... LeafImpl, class Others0, class... Others>
conditional_fun<
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...>>>
head_fun;
typedef conditional_fun<detail::tdata<Others0, Others...>> tail_fun;
return or_else(head_fun{other.m_leaves.head})
.or_else(tail_fun{other.m_leaves.tail()});
}
*/
//private:
// structure: tdata< tdata<type_list<...>, ...>,
......@@ -509,82 +707,199 @@ class conditional_fun
};
template<class ArgTypes, class Expr, class Guard, typename... TFuns>
conditional_fun<typename cfl_<ArgTypes, Expr, Guard, TFuns...>::type>
cfun(Expr e, Guard g, TFuns... tfs)
template<class List>
struct projected_fun_from_type_list;
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;
typedef typename util::get_callable_trait<Expr>::arg_types expr_args;
static_assert(ArgTypes::size >= expr_args::size,
"Functor has too many arguments");
return leaf_type{std::move(g), std::move(e), std::move(tfs)...};
typename detail::tdata_from_type_list<
typename util::tl_map<
typename util::tl_concat<
typename Arg0::leaves_list,
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
float tofloat(int i) { return i; }
template<typename... Args>
any_tuple make_any_tuple(Args&&... args)
{
return make_cow_tuple(std::forward<Args>(args)...);
}
struct dummy_guard
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>
{
};
template<typename FilteredPattern>
class value_guard
{
typename detail::tdata_from_type_list<FilteredPattern>::type m_args;
template<typename... Args>
inline bool operator()(Args const&...) const
inline bool _eval(util::void_type const&,
detail::tdata<> const&, Args&&...) 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:
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>
any_tuple make_any_tuple(Args&&... args)
{
return make_cow_tuple(std::forward<Args>(args)...);
}
typedef value_guard< util::type_list<> > dummy_guard;
struct from_args { };
struct cf_builder_from_args { };
template<class Guard, class Transformers, class Pattern>
struct cf_builder
{
typedef typename detail::tdata_from_type_list<Transformers>::type
fun_container;
Guard m_guard;
typename detail::tdata_from_type_list<Transformers>::type m_funs;
public:
cf_builder() = default;
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(G&& g) : m_guard(std::forward<G>(g))
cf_builder(Guard& mg, fun_container const& funs)
: m_guard(std::move(mg)), m_funs(funs)
{
}
template<typename G, typename F>
cf_builder(G&& g, F&& f) : m_guard(std::forward<G>(g)), m_funs(std::forward<F>(f))
cf_builder(Guard const& mg, fun_container const& funs)
: m_guard(mg), m_funs(funs)
{
}
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};
}
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
{
typedef conditional_fun_leaf<Expr, Guard, Transformers, Pattern> tfun;
return tfun{m_guard, std::move(expr), m_funs};
typedef typename get_cfl<Expr, Guard, Transformers, Pattern>::type tpair;
return tpair{typename tpair::first_type{m_funs},
typename tpair::second_type{std::move(expr), m_guard}};
}
};
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>
......@@ -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>
struct pattern_type_
{
......@@ -676,7 +953,7 @@ struct pattern_type_
template<typename 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>
......@@ -686,13 +963,24 @@ struct pattern_type : pattern_type_<util::is_callable<T>::value && !detail::is_b
template<typename Arg0, typename... Args>
cf_builder<
value_guard<typename util::tl_apply<util::type_list<Arg0, Args...>, boxed_and_callable_to_void>::type>,
typename util::tl_apply<util::type_list<Arg0, Args...>, not_callable_to_void>::type,
value_guard<
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,
typename pattern_type<Args>::type...> >
_on(Arg0 const& arg0, Args const&... args)
{
return {from_args{}, arg0, args...};
return {cf_builder_from_args{}, arg0, args...};
}
std::string int2str(int i)
......@@ -702,8 +990,12 @@ std::string int2str(int i)
option<int> str2int(std::string const& str)
{
if (str == "42") return 42;
if (str == "41") return 41;
char* endptr = nullptr;
int result = static_cast<int>(strtol(str.c_str(), &endptr, 10));
if (endptr != nullptr && *endptr == '\0')
{
return result;
}
return {};
}
......@@ -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()
{
CPPA_TEST(test__tuple);
......@@ -755,30 +1057,133 @@ size_t test__tuple()
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<float> token2;
//auto f00 = cfun<token1>([](int, int) { cout << "f0[1]!" << endl; }, _x1 > _x2)
// .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>() >> []() { };
auto f01 = _on<int, int>().when(_x1 == 42) >> []() { };
auto f02 = _on<int, int>().when(_x1 == 42 && _x2 * 2 == _x1) >> []() { };
auto f03 = _on(42, val<int>) >> [](int) { };
auto f04 = _on(42, int2str).when(_x2 == "42") >> []() { };
auto f05 = _on(42, str2int).when(_x2 % 2 == 0) >> []() { };
std::string invoked;
auto f00 = _on<int, int>() >> [&]() { invoked = "f00"; };
CPPA_CHECK_INVOKED(f00, (42, 42));
auto f01 = _on<int, int>().when(_x1 == 42) >> [&]() { invoked = "f01"; };
CPPA_CHECK_INVOKED(f01, (42, 42));
CPPA_CHECK_NOT_INVOKED(f01, (1, 2));
auto f02 = _on<int, int>().when(_x1 == 42 && _x2 * 2 == _x1) >> [&]() { invoked = "f02"; };
CPPA_CHECK_NOT_INVOKED(f02, (0, 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(f01(42, 42));
VERBOSE(f02(42, 42));
VERBOSE(f02(42, 21));
VERBOSE(f03(42, 42));
cout << detail::demangle(typeid(f04).name()) << endl;
VERBOSE(f04(42, 42));
VERBOSE(f04(42, std::string("42")));
......@@ -787,7 +1192,19 @@ size_t test__tuple()
VERBOSE(f05(42, std::string("42")));
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)
//.or_else(f00)
......@@ -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(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()
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