Commit d3d55a4c authored by neverlord's avatar neverlord

pattern matching

parent f246a9c9
......@@ -121,6 +121,7 @@ nobase_library_include_HEADERS = \
cppa/detail/post_office.hpp \
cppa/detail/post_office_msg.hpp \
cppa/detail/primitive_member.hpp \
cppa/detail/projection.hpp \
cppa/detail/ptype_to_type.hpp \
cppa/detail/receive_loop_helper.hpp \
cppa/detail/ref_counted_impl.hpp \
......@@ -132,12 +133,14 @@ nobase_library_include_HEADERS = \
cppa/detail/thread_pool_scheduler.hpp \
cppa/detail/to_uniform_name.hpp \
cppa/detail/tuple_cast_impl.hpp \
cppa/detail/tuple_iterator.hpp \
cppa/detail/tuple_vals.hpp \
cppa/detail/tuple_view.hpp \
cppa/detail/type_to_ptype.hpp \
cppa/detail/types_array.hpp \
cppa/detail/unboxed.hpp \
cppa/detail/uniform_type_info_map.hpp \
cppa/detail/value_guard.hpp \
cppa/detail/yield_interface.hpp \
cppa/detail/yielding_actor.hpp \
cppa/either.hpp \
......@@ -186,6 +189,7 @@ nobase_library_include_HEADERS = \
cppa/util/comparable.hpp \
cppa/util/compare_tuples.hpp \
cppa/util/conjunction.hpp \
cppa/util/deduce_ref_type.hpp \
cppa/util/disable_if.hpp \
cppa/util/disjunction.hpp \
cppa/util/duration.hpp \
......@@ -205,8 +209,10 @@ nobase_library_include_HEADERS = \
cppa/util/is_primitive.hpp \
cppa/util/left_or_right.hpp \
cppa/util/producer_consumer_list.hpp \
cppa/util/projection.hpp \
cppa/util/pt_dispatch.hpp \
cppa/util/pt_token.hpp \
cppa/util/purge_refs.hpp \
cppa/util/replace_type.hpp \
cppa/util/ripemd_160.hpp \
cppa/util/rm_option.hpp \
......
......@@ -262,3 +262,9 @@ cppa/util/left_or_right.hpp
cppa/util/apply_args.hpp
cppa/tpartial_function.hpp
cppa/util/rm_option.hpp
cppa/util/projection.hpp
cppa/util/purge_refs.hpp
cppa/util/deduce_ref_type.hpp
cppa/detail/projection.hpp
cppa/detail/value_guard.hpp
cppa/detail/tuple_iterator.hpp
......@@ -40,6 +40,8 @@
#include "cppa/util/type_list.hpp"
#include "cppa/detail/tuple_iterator.hpp"
namespace cppa { namespace detail {
enum tuple_impl_info
......@@ -85,87 +87,7 @@ class abstract_tuple : public ref_counted
bool equals(abstract_tuple const& other) const;
// iterator support
class const_iterator
{
size_t m_pos;
abstract_tuple const* m_tuple;
public:
inline const_iterator(abstract_tuple const* tup, size_t pos = 0)
: m_pos(pos), m_tuple(tup)
{
}
const_iterator(const_iterator const&) = default;
const_iterator& operator=(const_iterator const&) = default;
inline bool operator==(const_iterator const& other) const
{
CPPA_REQUIRE(other.m_tuple == other.m_tuple);
return other.m_pos == m_pos;
}
inline bool operator!=(const_iterator const& other) const
{
return !(*this == other);
}
inline const_iterator& operator++()
{
++m_pos;
return *this;
}
inline const_iterator& operator--()
{
CPPA_REQUIRE(m_pos > 0);
--m_pos;
return *this;
}
inline const_iterator operator+(size_t offset)
{
return {m_tuple, m_pos + offset};
}
inline const_iterator& operator+=(size_t offset)
{
m_pos += offset;
return *this;
}
inline const_iterator operator-(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
return {m_tuple, m_pos - offset};
}
inline const_iterator& operator-=(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
m_pos -= offset;
return *this;
}
inline size_t position() const { return m_pos; }
inline void const* value() const
{
return m_tuple->at(m_pos);
}
inline uniform_type_info const* type() const
{
return m_tuple->type_at(m_pos);
}
inline const_iterator& operator*() { return *this; }
};
typedef tuple_iterator<abstract_tuple> const_iterator;
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
......@@ -175,24 +97,41 @@ class abstract_tuple : public ref_counted
};
inline bool full_eq_v3(abstract_tuple::const_iterator const& lhs,
abstract_tuple::const_iterator const& rhs)
struct full_eq_type
{
constexpr full_eq_type() { }
template<class Tuple>
inline bool operator()(tuple_iterator<Tuple> const& lhs,
tuple_iterator<Tuple> const& rhs) const
{
return lhs.type() == rhs.type()
&& lhs.type()->equals(lhs.value(), rhs.value());
}
}
};
inline bool types_only_eq(abstract_tuple::const_iterator const& lhs,
uniform_type_info const* rhs)
struct types_only_eq_type
{
constexpr types_only_eq_type() { }
template<class Tuple>
inline bool operator()(tuple_iterator<Tuple> const& lhs,
uniform_type_info const* rhs ) const
{
return lhs.type() == rhs;
}
inline bool types_only_eq_v2(uniform_type_info const* lhs,
abstract_tuple::const_iterator const& rhs)
{
}
template<class Tuple>
inline bool operator()(uniform_type_info const* lhs,
tuple_iterator<Tuple> const& rhs) const
{
return lhs == rhs.type();
}
}
};
namespace {
constexpr full_eq_type full_eq;
constexpr types_only_eq_type types_only_eq;
} // namespace <anonymous>
} } // namespace cppa::detail
......
......@@ -38,13 +38,13 @@
namespace cppa { namespace detail {
template<wildcard_position, typename...>
template<wildcard_position, class Tuple, typename...>
struct matcher;
template<typename... T>
struct matcher<wildcard_position::nil, T...>
template<class Tuple, typename... T>
struct matcher<wildcard_position::nil, Tuple, T...>
{
static inline bool tmatch(any_tuple const& tup)
static inline bool tmatch(Tuple const& tup)
{
if (tup.impl_type() == tuple_impl_info::statically_typed)
{
......@@ -55,14 +55,14 @@ struct matcher<wildcard_position::nil, T...>
// always use a full dynamic match for dynamic typed tuples
else if (tup.size() == sizeof...(T))
{
auto& tarr = detail::static_types_array<T...>::arr;
auto& tarr = static_types_array<T...>::arr;
return std::equal(tup.begin(), tup.end(), tarr.begin(),
detail::types_only_eq);
types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
static inline bool tmatch(Tuple const& tup,
util::fixed_vector<size_t, sizeof...(T)>& mv)
{
if (tmatch(tup))
......@@ -74,31 +74,31 @@ struct matcher<wildcard_position::nil, T...>
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
static inline bool vmatch(Tuple const& tup, pattern<T...> const& ptrn)
{
CPPA_REQUIRE(tup.size() == sizeof...(T));
return ptrn._matches_values(tup);
}
};
template<typename... T>
struct matcher<wildcard_position::trailing, T...>
template<class Tuple, typename... T>
struct matcher<wildcard_position::trailing, Tuple, T...>
{
static constexpr size_t size = sizeof...(T) - 1;
static inline bool tmatch(any_tuple const& tup)
static inline bool tmatch(Tuple const& tup)
{
if (tup.size() >= size)
{
auto& tarr = static_types_array<T...>::arr;
auto begin = tup.begin();
return std::equal(begin, begin + size, tarr.begin(),
detail::types_only_eq);
types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
static inline bool tmatch(Tuple const& tup,
util::fixed_vector<size_t, size>& mv)
{
if (tmatch(tup))
......@@ -110,35 +110,35 @@ struct matcher<wildcard_position::trailing, T...>
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
static inline bool vmatch(Tuple const& tup, pattern<T...> const& ptrn)
{
return ptrn._matches_values(tup);
}
};
template<>
struct matcher<wildcard_position::leading, anything>
template<class Tuple>
struct matcher<wildcard_position::leading, Tuple, anything>
{
static inline bool tmatch(any_tuple const&)
static inline bool tmatch(Tuple const&)
{
return true;
}
static inline bool tmatch(any_tuple const&, util::fixed_vector<size_t, 0>&)
static inline bool tmatch(Tuple const&, util::fixed_vector<size_t, 0>&)
{
return true;
}
static inline bool vmatch(any_tuple const&, pattern<anything> const&)
static inline bool vmatch(Tuple const&, pattern<anything> const&)
{
return true;
}
};
template<typename... T>
struct matcher<wildcard_position::leading, T...>
template<class Tuple, typename... T>
struct matcher<wildcard_position::leading, Tuple, T...>
{
static constexpr size_t size = sizeof...(T) - 1;
static inline bool tmatch(any_tuple const& tup)
static inline bool tmatch(Tuple const& tup)
{
auto tup_size = tup.size();
if (tup_size >= size)
......@@ -148,12 +148,12 @@ struct matcher<wildcard_position::leading, T...>
begin += (tup_size - size);
return std::equal(begin, tup.end(),
(tarr.begin() + 1), // skip 'anything'
detail::types_only_eq);
types_only_eq);
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
static inline bool tmatch(Tuple const& tup,
util::fixed_vector<size_t, size>& mv)
{
if (tmatch(tup))
......@@ -165,14 +165,14 @@ struct matcher<wildcard_position::leading, T...>
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
static inline bool vmatch(Tuple const& tup, pattern<T...> const& ptrn)
{
return ptrn._matches_values(tup);
}
};
template<typename... T>
struct matcher<wildcard_position::in_between, T...>
template<class Tuple, typename... T>
struct matcher<wildcard_position::in_between, Tuple, T...>
{
static constexpr int signed_wc_pos =
util::tl_find<util::type_list<T...>, anything>::value;
......@@ -184,7 +184,7 @@ struct matcher<wildcard_position::in_between, T...>
&& signed_wc_pos != (sizeof...(T) - 1),
"illegal wildcard position");
static inline bool tmatch(any_tuple const& tup)
static inline bool tmatch(Tuple const& tup)
{
auto tup_size = tup.size();
if (tup_size >= size)
......@@ -193,19 +193,19 @@ struct matcher<wildcard_position::in_between, T...>
// first range [0, X1)
auto begin = tup.begin();
auto end = begin + wc_pos;
if (std::equal(begin, end, tarr.begin(), detail::types_only_eq))
if (std::equal(begin, end, tarr.begin(), types_only_eq))
{
// second range [X2, N)
begin = end = tup.end();
begin -= (size - (wc_pos + 1));
auto arr_begin = tarr.begin() + (wc_pos + 1);
return std::equal(begin, end, arr_begin, detail::types_only_eq);
return std::equal(begin, end, arr_begin, types_only_eq);
}
}
return false;
}
static inline bool tmatch(any_tuple const& tup,
static inline bool tmatch(Tuple const& tup,
util::fixed_vector<size_t, size - 1>& mv)
{
if (tmatch(tup))
......@@ -222,14 +222,14 @@ struct matcher<wildcard_position::in_between, T...>
return false;
}
static inline bool vmatch(any_tuple const& tup, pattern<T...> const& ptrn)
static inline bool vmatch(Tuple const& tup, pattern<T...> const& ptrn)
{
return ptrn._matches_values(tup);
}
};
template<typename... T>
struct matcher<wildcard_position::multiple, T...>
template<class Tuple, typename... T>
struct matcher<wildcard_position::multiple, Tuple, T...>
{
static constexpr size_t wc_count =
util::tl_count<util::type_list<T...>, is_anything>::value;
......@@ -240,7 +240,7 @@ struct matcher<wildcard_position::multiple, T...>
class Push, class Commit, class Rollback>
static bool match(TupleIter tbegin, TupleIter tend,
PatternIter pbegin, PatternIter pend,
Push&& push, Commit&& commit, Rollback&& rollback)
Push& push, Commit& commit, Rollback& rollback)
{
while (!(pbegin == pend && tbegin == tend))
{
......@@ -249,7 +249,7 @@ struct matcher<wildcard_position::multiple, T...>
// reached end of pattern while some values remain unmatched
return false;
}
else if (pbegin.type() == nullptr) // nullptr == wildcard (anything)
else if (*pbegin == nullptr) // nullptr == wildcard (anything)
{
// perform submatching
++pbegin;
......@@ -271,7 +271,7 @@ struct matcher<wildcard_position::multiple, T...>
return false; // no submatch found
}
// compare types
else if (tbegin.type() == pbegin.type()) push(tbegin);
else if (tbegin.type() == *pbegin) push(tbegin);
// no match
else return false;
// next iteration
......@@ -281,38 +281,40 @@ struct matcher<wildcard_position::multiple, T...>
return true; // pbegin == pend && tbegin == tend
}
static inline bool tmatch(any_tuple const& tup)
static inline bool tmatch(Tuple const& tup)
{
auto& tarr = static_types_array<T...>::arr;
if (tup.size() >= (sizeof...(T) - wc_count))
{
auto fpush = [](typename Tuple::const_iterator const&) { };
auto fcommit = []() { };
auto frollback = []() { };
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
[](any_tuple::const_iterator const&) { },
[]() { },
[]() { });
fpush, fcommit, frollback);
}
return false;
}
template<class MappingVector>
static inline bool tmatch(any_tuple const& tup, MappingVector& mv)
static inline bool tmatch(Tuple const& tup, MappingVector& mv)
{
auto& tarr = static_types_array<T...>::arr;
if (tup.size() >= (sizeof...(T) - wc_count))
{
size_t commited_size = 0;
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
[&](any_tuple::const_iterator const& iter)
auto fpush = [&](typename Tuple::const_iterator const& iter)
{
mv.push_back(iter.position());
},
[&]() { commited_size = mv.size(); },
[&]() { mv.resize(commited_size); });
};
auto fcommit = [&]() { commited_size = mv.size(); };
auto frollback = [&]() { mv.resize(commited_size); };
return match(tup.begin(), tup.end(), tarr.begin(), tarr.end(),
fpush, fcommit, frollback);
}
return false;
}
static inline bool vmatch(any_tuple const& tup,
static inline bool vmatch(Tuple const& tup,
pattern<T...> const& ptrn,
typename pattern<T...>::mapping_vector const& mv)
{
......@@ -321,81 +323,93 @@ struct matcher<wildcard_position::multiple, T...>
};
// implementation for zero or one wildcards
template<wildcard_position PC, typename... Ts>
template<wildcard_position PC, class Tuple, typename... Ts>
struct match_impl
{
static inline bool _(any_tuple const& tup)
static inline bool _(Tuple const& tup)
{
return detail::matcher<PC, Ts...>::tmatch(tup);
return matcher<PC, Tuple, Ts...>::tmatch(tup);
}
template<size_t Size>
static inline bool _(any_tuple const& tup,
static inline bool _(Tuple const& tup,
util::fixed_vector<size_t, Size>& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv);
}
static inline bool _(any_tuple const& tup,
static inline bool _(Tuple const& tup,
pattern<Ts...> const& p)
{
return detail::matcher<PC, Ts...>::tmatch(tup)
return matcher<PC, Tuple, Ts...>::tmatch(tup)
&& ( p.has_values() == false
|| detail::matcher<PC, Ts...>::vmatch(tup, p));
|| matcher<PC, Tuple, Ts...>::vmatch(tup, p));
}
static inline bool _(any_tuple const& tup,
static inline bool _(Tuple const& tup,
pattern<Ts...> const& p,
typename pattern<Ts...>::mapping_vector& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv)
&& ( p.has_values() == false
|| detail::matcher<PC, Ts...>::vmatch(tup, p));
|| matcher<PC, Tuple, Ts...>::vmatch(tup, p));
}
};
// implementation for multiple wildcards
template<typename... Ts>
struct match_impl<wildcard_position::multiple, Ts...>
template<class Tuple, typename... Ts>
struct match_impl<wildcard_position::multiple, Tuple, Ts...>
{
static constexpr auto PC = wildcard_position::multiple;
static inline bool _(any_tuple const& tup)
static inline bool _(Tuple const& tup)
{
return detail::matcher<PC, Ts...>::tmatch(tup);
return matcher<PC, Tuple, Ts...>::tmatch(tup);
}
template<size_t Size>
static inline bool _(any_tuple const& tup,
static inline bool _(Tuple const& tup,
util::fixed_vector<size_t, Size>& mv)
{
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv);
}
static inline bool _(any_tuple const& tup, pattern<Ts...> const& p)
static inline bool _(Tuple const& tup, pattern<Ts...> const& p)
{
if (p.has_values())
{
typename pattern<Ts...>::mapping_vector mv;
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
&& detail::matcher<PC, Ts...>::vmatch(tup, p, mv);
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv)
&& matcher<PC, Tuple, Ts...>::vmatch(tup, p, mv);
}
return detail::matcher<PC, Ts...>::tmatch(tup);
return matcher<PC, Tuple, Ts...>::tmatch(tup);
}
static inline bool _(any_tuple const& tup, pattern<Ts...> const& p,
static inline bool _(Tuple const& tup, pattern<Ts...> const& p,
typename pattern<Ts...>::mapping_vector& mv)
{
if (p.has_values())
{
typename pattern<Ts...>::mapping_vector mv;
return detail::matcher<PC, Ts...>::tmatch(tup, mv)
&& detail::matcher<PC, Ts...>::vmatch(tup, p, mv);
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv)
&& matcher<PC, Tuple, Ts...>::vmatch(tup, p, mv);
}
return detail::matcher<PC, Ts...>::tmatch(tup, mv);
return matcher<PC, Tuple, Ts...>::tmatch(tup, mv);
}
};
template<class Tuple, class List>
class match_impl_from_type_list;
template<class Tuple, typename... Ts>
struct match_impl_from_type_list<Tuple, util::type_list<Ts...> >
{
typedef match_impl<get_wildcard_position<util::type_list<Ts...> >(),
Tuple,
Ts...>
type;
};
/*
* @brief Returns true if this tuple matches the pattern <tt>{Ts...}</tt>.
*/
......@@ -403,7 +417,8 @@ template<typename... Ts>
bool matches(any_tuple const& tup)
{
typedef util::type_list<Ts...> tl;
return detail::match_impl<get_wildcard_position<tl>(), Ts...>::_(tup);
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
::_(tup);
}
/*
......@@ -418,7 +433,8 @@ bool matches(any_tuple const& tup,
is_anything>::value>& mv)
{
typedef util::type_list<Ts...> tl;
return detail::match_impl<get_wildcard_position<tl>(), Ts...>::_(tup, mv);
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
::_(tup, mv);
}
/*
......@@ -428,7 +444,8 @@ template<typename... Ts>
bool matches(any_tuple const& tup, pattern<Ts...> const& pn)
{
typedef util::type_list<Ts...> tl;
return detail::match_impl<get_wildcard_position<tl>(), Ts...>::_(tup, pn);
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
::_(tup, pn);
}
/*
......@@ -439,9 +456,8 @@ bool matches(any_tuple const& tup, pattern<Ts...> const& pn,
typename pattern<Ts...>::mapping_vector& mv)
{
typedef util::type_list<Ts...> tl;
return detail::match_impl<get_wildcard_position<tl>(), Ts...>::_(tup,
pn,
mv);
return match_impl<get_wildcard_position<tl>(), any_tuple, Ts...>
::_(tup, pn, mv);
}
// support for type_list based matching
......@@ -459,7 +475,7 @@ inline bool matches(any_tuple const& tup, util::type_list<Ts...> const&,
util::type_list<Ts...>,
is_anything>::value>& mv)
{
return matches<Ts...>(mv);
return matches<Ts...>(tup, mv);
}
/*
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 PROJECTION_HPP
#define PROJECTION_HPP
#include "cppa/option.hpp"
#include "cppa/guard_expr.hpp"
#include "cppa/util/rm_option.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/apply_tuple.hpp"
#include "cppa/util/left_or_right.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa { namespace detail {
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;
}
};
/**
* @brief Projection implemented by a set of functors.
*/
template<class ProjectionFuns, typename... Args>
class projection
{
public:
typedef typename tdata_from_type_list<ProjectionFuns>::type fun_container;
projection(fun_container const& args) : m_funs(args) { }
projection(projection const&) = default;
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
template<class PartialFun>
bool operator()(PartialFun& fun, Args... args) const
{
typedef typename util::tl_zip<
typename util::tl_map<
ProjectionFuns,
util::get_result_type,
util::rm_option
>::type,
typename util::tl_map<
util::type_list<Args...>,
mutable_gref_wrapped
>::type,
util::left_or_right
>::type
collected_args;
typename tdata_from_type_list<collected_args>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...))
{
projection_helper<PartialFun> helper{fun};
return util::unchecked_apply_tuple<bool>(helper, pargs);
}
return false;
}
private:
template<typename Storage, typename T>
static inline bool fetch_(Storage& storage, T&& value)
{
storage = std::forward<T>(value);
return true;
}
template<class Storage>
static inline bool fetch_(Storage& storage, option<Storage>&& value)
{
if (value)
{
storage = std::move(*value);
return true;
}
return false;
}
template<class Storage, typename Fun, typename T>
static inline bool fetch(Storage& storage, Fun const& fun, T&& arg)
{
return fetch_(storage, fun(std::forward<T>(arg)));
}
template<typename Storage, typename T>
static inline bool fetch(Storage& storage, util::void_type const&, T&& arg)
{
return fetch_(storage, std::forward<T>(arg));
}
static inline bool collect(tdata<>&, tdata<> const&)
{
return true;
}
template<class TData, class Trans, typename T0, typename... Ts>
static inline bool collect(TData& td, Trans const& tr,
T0&& arg0, Ts&&... args)
{
return fetch(td.head, tr.head, std::forward<T0>(arg0))
&& collect(td.tail(), tr.tail(), std::forward<Ts>(args)...);
}
fun_container m_funs;
};
template<>
class projection<util::type_list<> >
{
public:
projection() = default;
projection(tdata<> const&) { }
projection(projection const&) = default;
template<class PartialFun>
bool operator()(PartialFun& fun) const
{
fun();
return true;
}
};
template<class ProjectionFuns, class List>
class projection_from_type_list;
template<class ProjectionFuns, typename... Args>
class projection_from_type_list<ProjectionFuns, util::type_list<Args...> >
{
typedef projection<ProjectionFuns, Args...> type;
};
} } // namespace cppa::detail
#endif // PROJECTION_HPP
......@@ -47,6 +47,7 @@
#include "cppa/detail/boxed.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/abstract_tuple.hpp"
#include "cppa/detail/tuple_iterator.hpp"
#include "cppa/detail/implicit_conversions.hpp"
namespace cppa {
......@@ -154,6 +155,14 @@ struct tdata<>
"Additional unboxed arguments provided");
}
typedef tuple_iterator<tdata> const_iterator;
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
inline const_iterator end() const { return {this}; }
inline const_iterator cend() const { return {this}; }
inline tdata(tdata&) { }
inline tdata(tdata&&) { }
inline tdata(tdata const&) { }
......@@ -310,6 +319,15 @@ struct tdata<Head, Tail...> : tdata<Tail...>
inline size_t size() const { return num_elements; }
typedef tuple_iterator<tdata> const_iterator;
inline const_iterator begin() const { return {this}; }
inline const_iterator cbegin() const { return {this}; }
inline const_iterator end() const { return {this, size()}; }
inline const_iterator cend() const { return {this, size()}; }
// upcast
inline tdata<Tail...>& tail() { return *this; }
......@@ -427,6 +445,22 @@ struct tdata_from_type_list<util::type_list<T...>>
typedef tdata<T...> type;
};
template<typename... T>
inline void collect_tdata(tdata<T...>&) { }
template<typename Storage, typename... Args>
void collect_tdata(Storage& storage, tdata<> const&, Args const&... args)
{
collect_tdata(storage, args...);
}
template<typename Storage, typename Arg0, typename... Args>
void collect_tdata(Storage& storage, Arg0 const& arg0, Args const&... args)
{
storage.head = arg0.head;
collect_tdata(storage.tail(), arg0.tail(), args...);
}
} } // namespace cppa::detail
namespace cppa {
......
......@@ -59,7 +59,8 @@ struct tuple_cast_impl
static constexpr size_t size =
util::tl_count_not<util::type_list<T...>, is_anything>::value;
static constexpr size_t first_wc =
static_cast<size_t>(util::tl_find<util::type_list<T...>, anything>::value);
static_cast<size_t>(
util::tl_find<util::type_list<T...>, anything>::value);
typedef util::fixed_vector<size_t, size> mapping_vector;
static inline option<Result> safe(any_tuple& tup)
{
......@@ -80,7 +81,7 @@ struct tuple_cast_impl
mapping_vector mv;
if (WP == wildcard_position::in_between)
{
if (!p.has_values() || matcher<WP, T...>::vmatch(tup, p))
if (!p.has_values() || matcher<WP, any_tuple, T...>::vmatch(tup, p))
{
// first range
mv.resize(size);
......@@ -140,7 +141,7 @@ struct tuple_cast_impl<wildcard_position::nil, Result, T...>
static inline option<Result> unsafe(any_tuple& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::nil, T...>::vmatch(tup, p))
|| matcher<wildcard_position::nil, any_tuple, T...>::vmatch(tup, p))
{
return {Result::from(std::move(tup.vals()))};
}
......@@ -159,7 +160,8 @@ struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
static inline option<Result> unsafe(any_tuple& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::trailing, T...>::vmatch(tup, p))
|| matcher<wildcard_position::trailing, any_tuple, T...>
::vmatch(tup, p))
{
return {Result::from(std::move(tup.vals()))};
}
......@@ -189,7 +191,8 @@ struct tuple_cast_impl<wildcard_position::leading, Result, T...>
static inline option<Result> unsafe(any_tuple& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::leading, T...>::vmatch(tup, p))
|| matcher<wildcard_position::leading, any_tuple, T...>
::vmatch(tup, p))
{
size_t o = tup.size() - (sizeof...(T) - 1);
return Result::offset_subtuple(tup.vals(), o);
......
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 TUPLE_ITERATOR_HPP
#define TUPLE_ITERATOR_HPP
#include <cstddef>
#include "cppa/config.hpp"
namespace cppa { namespace detail {
template<class Tuple>
class tuple_iterator
{
size_t m_pos;
Tuple const* m_tuple;
public:
inline tuple_iterator(Tuple const* tup, size_t pos = 0)
: m_pos(pos), m_tuple(tup)
{
}
tuple_iterator(tuple_iterator const&) = default;
tuple_iterator& operator=(tuple_iterator const&) = default;
inline bool operator==(tuple_iterator const& other) const
{
CPPA_REQUIRE(other.m_tuple == other.m_tuple);
return other.m_pos == m_pos;
}
inline bool operator!=(tuple_iterator const& other) const
{
return !(*this == other);
}
inline tuple_iterator& operator++()
{
++m_pos;
return *this;
}
inline tuple_iterator& operator--()
{
CPPA_REQUIRE(m_pos > 0);
--m_pos;
return *this;
}
inline tuple_iterator operator+(size_t offset)
{
return {m_tuple, m_pos + offset};
}
inline tuple_iterator& operator+=(size_t offset)
{
m_pos += offset;
return *this;
}
inline tuple_iterator operator-(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
return {m_tuple, m_pos - offset};
}
inline tuple_iterator& operator-=(size_t offset)
{
CPPA_REQUIRE(m_pos >= offset);
m_pos -= offset;
return *this;
}
inline size_t position() const { return m_pos; }
inline void const* value() const
{
return m_tuple->at(m_pos);
}
inline uniform_type_info const* type() const
{
return m_tuple->type_at(m_pos);
}
inline tuple_iterator& operator*() { return *this; }
};
} } // namespace cppa::detail
#endif // TUPLE_ITERATOR_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 VALUE_GUARD_HPP
#define VALUE_GUARD_HPP
#include "cppa/util/rm_ref.hpp"
#include "cppa/util/void_type.hpp"
#include "cppa/util/type_list.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/tdata.hpp"
namespace cppa { namespace detail {
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 callables
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 tdata_from_type_list<FilteredPattern>::type m_args;
template<typename... Args>
inline bool _eval(util::void_type const&, 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...);
}
};
} } // namespace cppa::detail
#endif // VALUE_GUARD_HPP
......@@ -729,6 +729,26 @@ bool guard_expr<OP, First, Second>::operator()(Args const&... args) const
return ge_invoke(*this, args...);
}
// some utility functions
template<typename T>
struct gref_wrapped
{
typedef ge_reference_wrapper<typename util::rm_ref<T>::type> type;
};
template<typename T>
struct mutable_gref_wrapped
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct mutable_gref_wrapped<T&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
// finally ...
namespace placeholders { namespace {
......
......@@ -108,13 +108,6 @@ struct get_arg_types
typedef typename trait_type::arg_types types;
};
template<typename C>
struct get_result_type
{
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename T>
struct is_callable
{
......@@ -142,6 +135,25 @@ struct is_callable
};
template<bool IsCallable, typename C>
struct get_result_type_impl
{
typedef typename get_callable_trait<C>::type trait_type;
typedef typename trait_type::result_type type;
};
template<typename C>
struct get_result_type_impl<false, C>
{
typedef void_type type;
};
template<typename C>
struct get_result_type
{
typedef typename get_result_type_impl<is_callable<C>::value, C>::type type;
};
} } // namespace cppa::util
#endif // CPPA_UTIL_CALLABLE_TRAIT
/******************************************************************************\
* ___ __ *
* /\_ \ __/\ \ *
* \//\ \ /\_\ \ \____ ___ _____ _____ __ *
* \ \ \ \/\ \ \ '__`\ /'___\/\ '__`\/\ '__`\ /'__`\ *
* \_\ \_\ \ \ \ \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 DEDUCE_REF_TYPE_HPP
#define DEDUCE_REF_TYPE_HPP
#include "cppa/util/rm_ref.hpp"
namespace cppa { namespace util {
/**
* @brief Deduces reference type of T0 and applies it to T1.
*/
template<typename T0, typename T1>
struct deduce_ref_type
{
typedef typename util::rm_ref<T1>::type type;
};
template<typename T0, typename T1>
struct deduce_ref_type<T0&, T1>
{
typedef typename util::rm_ref<T1>::type& type;
};
template<typename T0, typename T1>
struct deduce_ref_type<T0 const&, T1>
{
typedef typename util::rm_ref<T1>::type const& type;
};
} } // namespace cppa::util
#endif // DEDUCE_REF_TYPE_HPP
......@@ -50,6 +50,33 @@ struct left_or_right<util::void_type, Right>
typedef Right type;
};
template<typename Right>
struct left_or_right<util::void_type&, Right>
{
typedef Right type;
};
template<typename Right>
struct left_or_right<util::void_type const&, Right>
{
typedef Right type;
};
/**
* @brief Evaluates to @p Right if @p Left != void_type, @p void_type otherwise.
*/
template<typename Left, typename Right>
struct if_not_left
{
typedef void_type type;
};
template<typename Right>
struct if_not_left<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 PROJECTION_HPP
#define PROJECTION_HPP
namespace cppa { namespace util {
} } // namespace cppa::util
#endif // PROJECTION_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 PURGE_REFS_HPP
#define PURGE_REFS_HPP
#include <functional>
#include "cppa/guard_expr.hpp"
#include "cppa/util/rm_ref.hpp"
namespace cppa { namespace util {
template<typename T>
struct purge_refs_impl
{
typedef T type;
};
template<typename T>
struct purge_refs_impl<ge_reference_wrapper<T> >
{
typedef T type;
};
template<typename T>
struct purge_refs_impl<ge_mutable_reference_wrapper<T> >
{
typedef T type;
};
template<typename T>
struct purge_refs_impl<std::reference_wrapper<T> >
{
typedef T type;
};
/**
* @brief Removes references and reference wrappers.
*/
template<typename T>
struct purge_refs
{
typedef typename purge_refs_impl<typename util::rm_ref<T>::type>::type type;
};
} } // namespace cppa::util
#endif // PURGE_REFS_HPP
......@@ -554,18 +554,93 @@ struct tl_push_front<type_list<ListTypes...>, What>
// list map(list, trait)
template<typename T, template<typename> class... Funs>
struct tl_apply_all;
template<typename T>
struct tl_apply_all<T>
{
typedef T type;
};
template<typename T,
template<typename> class Fun0,
template<typename> class... Funs>
struct tl_apply_all<T, Fun0, Funs...>
{
typedef typename tl_apply_all<typename Fun0<T>::type, Funs...>::type type;
};
/**
* @brief Creates a new list by applying a "template function" to each element.
*/
template<class List, template<typename> class Fun>
template<class List, template<typename> class... Funs>
struct tl_map;
template<template<typename> class Fun, typename... Elements>
struct tl_map<type_list<Elements...>, Fun>
template<typename... Ts, template<typename> class... Funs>
struct tl_map<type_list<Ts...>, Funs...>
{
typedef type_list<typename Fun<Elements>::type...> type;
typedef type_list<typename tl_apply_all<Ts, Funs...>::type...> type;
};
/**
* @brief Creates a new list by applying a @p Fun to each element which
* returns @p TraitResult for @p Trait.
*/
template<class List,
template<typename> class Trait,
bool TraitResult,
template<typename> class... Funs>
struct tl_map_conditional
{
typedef typename tl_concat<
type_list<
typename std::conditional<
Trait<typename List::head>::value == TraitResult,
typename tl_apply_all<typename List::head, Funs...>::type,
typename List::head
>::type
>,
typename tl_map_conditional<
typename List::tail,
Trait,
TraitResult,
Funs...
>::type
>::type
type;
};
template<template<typename> class Trait,
bool TraitResult,
template<typename> class... Funs>
struct tl_map_conditional<type_list<>, Trait, TraitResult, Funs...>
{
typedef type_list<> type;
};
/*
freaks GCC out ...
template<typename... Ts,
template<typename> class Trait,
bool TraitResult,
template<typename> class... Funs>
struct tl_map_conditional<type_list<Ts...>, Trait, TraitResult, Funs...>
{
typedef type_list<
typename std::conditional<
Trait<Ts>::value == TraitResult,
typename tl_apply_all<Ts, Funs...>::type,
Ts
>::type
...
type;
};
*/
// list zipped_map(trait)
template<class List, template<typename, typename> class Fun>
......@@ -590,8 +665,13 @@ struct tl_zipped_map<type_list<T...>, Fun>
template<class List>
struct tl_pop_back
{
typedef typename tl_reverse<List>::type rlist;
typedef typename tl_reverse<typename rlist::tail>::type type;
typedef typename tl_slice<List, 0, List::size - 1>::type type;
};
template<>
struct tl_pop_back<type_list<> >
{
typedef type_list<> type;
};
// type at(size_t)
......@@ -833,7 +913,7 @@ struct tl_is_zipped
/**
* @brief Removes trailing @p What elements from the end.
*/
template<class List, typename What>
template<class List, typename What = void_type>
struct tl_trim
{
typedef typename util::if_else<
......
......@@ -36,7 +36,7 @@ bool abstract_tuple::equals(const abstract_tuple &other) const
{
return this == &other
|| ( size() == other.size()
&& std::equal(begin(), end(), other.begin(), detail::full_eq_v3));
&& std::equal(begin(), end(), other.begin(), detail::full_eq));
}
abstract_tuple::abstract_tuple(abstract_tuple const& other)
......
......@@ -20,9 +20,14 @@
#include "cppa/uniform_type_info.hpp"
#include "cppa/util/rm_option.hpp"
#include "cppa/util/purge_refs.hpp"
#include "cppa/util/deduce_ref_type.hpp"
#include "cppa/detail/matches.hpp"
#include "cppa/detail/invokable.hpp"
#include "cppa/detail/projection.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/value_guard.hpp"
#include "cppa/detail/object_array.hpp"
#include <boost/progress.hpp>
......@@ -31,96 +36,110 @@ using std::cout;
using std::endl;
using namespace cppa;
using namespace cppa::detail;
template<typename... T>
struct dummy_tuple
struct pseudo_tuple
{
typedef void* ptr_type;
typedef void const* const_ptr_type;
ptr_type data[sizeof...(T) > 0 ? sizeof...(T) : 1];
inline const_ptr_type at(size_t p) const
{
return data[p];
}
inline ptr_type mutable_at(size_t p)
{
return const_cast<ptr_type>(data[p]);
}
void*& operator[](size_t p)
inline void*& operator[](size_t p)
{
return data[p];
}
};
template<class List>
struct pseudo_tuple_from_type_list;
template<typename... Ts>
struct pseudo_tuple_from_type_list<util::type_list<Ts...> >
{
typedef pseudo_tuple<Ts...> type;
};
template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type const& get(dummy_tuple<Tn...> const& tv)
typename util::at<N, Tn...>::type const& get(pseudo_tuple<Tn...> const& tv)
{
static_assert(N < sizeof...(Tn), "N >= tv.size()");
return *reinterpret_cast<typename util::at<N, Tn...>::type const*>(tv.at(N));
}
template<size_t N, typename... Tn>
typename util::at<N, Tn...>::type& get_ref(dummy_tuple<Tn...>& tv)
typename util::at<N, Tn...>::type& get_ref(pseudo_tuple<Tn...>& tv)
{
static_assert(N < sizeof...(Tn), "N >= tv.size()");
return *reinterpret_cast<typename util::at<N, Tn...>::type*>(tv.mutable_at(N));
}
template<typename T>
struct gref_wrapped
{
typedef ge_reference_wrapper<typename util::rm_ref<T>::type> type;
};
template<typename T>
struct gref_mutable_wrapped
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct gref_mutable_wrapped<T&>
{
typedef ge_mutable_reference_wrapper<T> type;
};
template<typename T>
struct rm_all_refs_
{
typedef T type;
};
template<typename T>
struct rm_all_refs_<ge_reference_wrapper<T> >
{
typedef T type;
};
template<typename T>
struct rm_all_refs_<ge_mutable_reference_wrapper<T> >
// covers wildcard_position::multiple and wildcard_position::in_between
template<wildcard_position, class Pattern, class FilteredPattern>
struct invoke_policy_impl
{
typedef T type;
};
typedef FilteredPattern filtered_pattern;
template<typename T>
struct rm_all_refs_<std::reference_wrapper<T> >
{
typedef T type;
};
template<class Tuple>
static bool can_invoke(std::type_info const& type_token,
Tuple const& tup)
{
typedef typename match_impl_from_type_list<Tuple, Pattern>::type mimpl;
return type_token == typeid(filtered_pattern) || mimpl::_(tup);
}
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target,
std::type_info const& type_token,
detail::tuple_impl_info,
PtrType*,
Tuple& tup)
{
typedef typename match_impl_from_type_list<
typename std::remove_const<Tuple>::type,
Pattern
>::type
mimpl;
template<typename T>
struct rm_all_refs
{
typedef typename rm_all_refs_<typename util::rm_ref<T>::type>::type type;
util::fixed_vector<size_t, filtered_pattern::size> mv;
if (type_token == typeid(filtered_pattern) || mimpl::_(tup, mv))
{
typedef typename pseudo_tuple_from_type_list<filtered_pattern>::type
ttup_type;
ttup_type ttup;
// if we strip const here ...
for (size_t i = 0; i < filtered_pattern::size; ++i)
{
ttup[i] = const_cast<void*>(tup.at(mv[i]));
}
// ... we restore it here again
typedef typename util::if_else<
std::is_const<Tuple>,
ttup_type const&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
}
return false;
}
};
template<wildcard_position, class Pattern, class FilteredPattern>
struct invoke_policy_impl;
template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::nil, Pattern, util::type_list<Ts...> >
struct invoke_policy_impl<wildcard_position::nil,
Pattern, util::type_list<Ts...> >
{
typedef util::type_list<Ts...> filtered_pattern;
......@@ -128,59 +147,40 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, util::type_list<Ts...
typedef typename detail::static_types_array<Ts...> arr_type;
enum shortcut_result
template<class Target, class Tup>
static bool invoke(std::integral_constant<bool, false>, Target&, Tup&)
{
no_shortcut_available,
shortcut_failed,
shortcut_succeeded
};
return false;
}
template<class Target, class Tup>
static inline shortcut_result shortcut(Target&, Tup&)
static bool invoke(std::integral_constant<bool, true>,
Target& target, Tup& tup)
{
return no_shortcut_available;
return util::unchecked_apply_tuple<bool>(target, tup);
}
template<class Target, typename... T>
static inline shortcut_result shortcut(Target& target,
detail::tdata<T...> const& tup,
typename util::enable_if<
util::tl_binary_forall<
util::type_list<
typename rm_all_refs<T>::type...
>,
filtered_pattern,
std::is_same
>
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target,
std::type_info const&,
detail::tuple_impl_info,
PtrType*,
Tuple& tup,
typename util::disable_if<
std::is_same<typename std::remove_const<Tuple>::type,
detail::abstract_tuple>
>::type* = 0)
{
if (util::unchecked_apply_tuple<bool>(target, tup))
return shortcut_succeeded;
return shortcut_failed;
}
template<class Target, typename... T>
static inline shortcut_result shortcut(Target& target,
detail::tdata<T...>& tup,
typename util::enable_if<
static constexpr bool can_apply =
util::tl_binary_forall<
util::type_list<
typename rm_all_refs<T>::type...
>,
typename util::tl_map<
typename Tuple::types,
util::purge_refs
>::type,
filtered_pattern,
std::is_same
>
>::type* = 0)
{
if (util::unchecked_apply_tuple<bool>(target, tup))
return shortcut_succeeded;
return shortcut_failed;
}
template<class Tuple>
static bool can_invoke(std::type_info const& arg_types, Tuple const&)
{
return arg_types == typeid(filtered_pattern);
>::value;
return invoke(std::integral_constant<bool, can_apply>{}, target, tup);
}
template<class Target, typename PtrType, typename Tuple>
......@@ -188,14 +188,12 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, util::type_list<Ts...
std::type_info const& arg_types,
detail::tuple_impl_info timpl,
PtrType* native_arg,
Tuple& tup)
{
switch (shortcut(target, tup) )
Tuple& tup,
typename util::enable_if<
std::is_same<typename std::remove_const<Tuple>::type,
detail::abstract_tuple>
>::type* = 0)
{
case shortcut_succeeded: return true;
case shortcut_failed: return false;
default: ; // nop
}
if (arg_types == typeid(filtered_pattern))
{
if (native_arg)
......@@ -231,13 +229,11 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, util::type_list<Ts...
{
return false;
}
typedef dummy_tuple<PtrType*, Ts...> ttup_type;
typedef pseudo_tuple<Ts...> ttup_type;
ttup_type ttup;
// if we strip const here ...
for (size_t i = 0; i < sizeof...(Ts); ++i)
ttup[i] = const_cast<void*>(tup.at(i));
// ... we restore it here again
typedef typename util::if_else<
std::is_const<PtrType>,
......@@ -245,8 +241,14 @@ struct invoke_policy_impl<wildcard_position::nil, Pattern, util::type_list<Ts...
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
}
return util::unchecked_apply_tuple<bool>(target, static_cast<ttup_ref>(ttup));
template<class Tuple>
static bool can_invoke(std::type_info const& arg_types, Tuple const&)
{
return arg_types == typeid(filtered_pattern);
}
};
......@@ -262,19 +264,16 @@ struct invoke_policy_impl<wildcard_position::leading,
return true;
}
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target,
std::type_info const&,
detail::tuple_impl_info,
PtrType*,
Tuple&)
template<class Target, typename... Args>
static bool invoke(Target& target, Args&&...)
{
return target();
}
};
template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::trailing, Pattern, util::type_list<Ts...> >
struct invoke_policy_impl<wildcard_position::trailing,
Pattern, util::type_list<Ts...> >
{
typedef util::type_list<Ts...> filtered_pattern;
......@@ -304,37 +303,86 @@ struct invoke_policy_impl<wildcard_position::trailing, Pattern, util::type_list<
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target,
std::type_info const&,
std::type_info const& arg_types,
detail::tuple_impl_info,
PtrType*,
Tuple& tup)
{
if (!can_invoke(arg_types, tup)) return false;
typedef pseudo_tuple<Ts...> ttup_type;
ttup_type ttup;
for (size_t i = 0; i < sizeof...(Ts); ++i)
ttup[i] = const_cast<void*>(tup.at(i));
// ensure const-correctness
typedef typename util::if_else<
std::is_const<Tuple>,
ttup_type const&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
}
};
template<class Pattern, typename... Ts>
struct invoke_policy_impl<wildcard_position::leading,
Pattern, util::type_list<Ts...> >
{
typedef util::type_list<Ts...> filtered_pattern;
template<class Tuple>
static bool can_invoke(std::type_info const& arg_types,
Tuple const& tup)
{
if (arg_types == typeid(filtered_pattern))
{
return true;
}
typedef detail::static_types_array<Ts...> arr_type;
auto& arr = arr_type::arr;
if (tup.size() < filtered_pattern::size)
{
return false;
}
for (size_t i = 0; i < filtered_pattern::size; ++i)
size_t i = tup.size() - filtered_pattern::size;
size_t j = 0;
while (j < filtered_pattern::size)
{
if (arr[i] != tup.type_at(i))
if (arr[i++] != tup.type_at(j++))
{
return false;
}
}
typedef dummy_tuple<Ts...> ttup_type;
ttup_type ttup;
for (size_t i = 0; i < sizeof...(Ts); ++i)
ttup[i] = const_cast<void*>(tup.at(i));
return true;
}
template<class Target, typename PtrType, class Tuple>
static bool invoke(Target& target,
std::type_info const& arg_types,
detail::tuple_impl_info,
PtrType*,
Tuple& tup)
{
if (!can_invoke(arg_types, tup)) return false;
typedef pseudo_tuple<Ts...> ttup_type;
ttup_type ttup;
size_t i = tup.size() - filtered_pattern::size;
size_t j = 0;
while (j < filtered_pattern::size)
{
ttup[j++] = const_cast<void*>(tup.at(i++));
}
// ensure const-correctness
typedef typename util::if_else<
std::is_const<Tuple>,
ttup_type const&,
util::wrapped<ttup_type&>
>::type
ttup_ref;
return util::unchecked_apply_tuple<bool>(target, static_cast<ttup_ref>(ttup));
ttup_ref ttup_fwd = ttup;
return util::unchecked_apply_tuple<bool>(target, ttup_fwd);
}
};
......@@ -348,293 +396,108 @@ struct invoke_policy
{
};
template<class PartialFun>
struct projection_helper
template<class Pattern, class Projection, class PartialFunction>
struct projection_partial_function_pair : std::pair<Projection, PartialFunction>
{
PartialFun const& fun;
projection_helper(PartialFun const& pfun) : fun(pfun) { }
template<typename... Args>
bool operator()(Args&&... args) const
projection_partial_function_pair(Args&&... args)
: std::pair<Projection, PartialFunction>(std::forward<Args>(args)...)
{
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<typename T>
struct add_ref_if_not_void
{
typedef T& type;
};
template<>
struct add_ref_if_not_void<util::void_type>
{
typedef util::void_type type;
};
template<typename T>
struct deduce_result
{
typedef typename util::rm_option<typename util::get_result_type<T>::type>::type type;
};
template<>
struct deduce_result<util::void_type>
{
typedef util::void_type type;
};
template<typename T>
struct deduce_unary_arg
{
typedef typename util::get_arg_types<T>::types arg_types;
static_assert(arg_types::size == 1, "not a unary function");
typedef typename arg_types::head type;
};
template<>
struct deduce_unary_arg<util::void_type>
{
typedef util::void_type type;
};
template<typename T0, typename T1>
struct deduce_ref_type
{
typedef T1 type;
};
template<typename T>
struct deduce_ref_type<T&, T>
{
typedef T& type;
typedef Pattern pattern_type;
};
/**
* @brief Projection implemented by a set of functors.
*/
template<class Pattern, class TargetSignature, class ProjectionFuns>
class projection
template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl
{
typedef typename detail::tdata_from_type_list<ProjectionFuns>::type
fun_container;
fun_container m_funs;
public:
typedef Pattern pattern_type;
typedef typename util::get_callable_trait<Expr>::type ctrait;
typedef typename util::tl_filter_not_type<
pattern_type,
Pattern,
anything
>::type
filtered_pattern;
static_assert(ProjectionFuns::size <= filtered_pattern::size,
"invalid projection (too many functions)");
typedef typename util::tl_pad_left<
TargetSignature,
filtered_pattern::size
>::type
padded_signature;
typedef typename util::tl_pad_left<
ProjectionFuns,
typedef typename util::tl_pad_right<
Transformers,
filtered_pattern::size
>::type
padded_projection_funs;
padded_transformers;
typedef typename util::tl_map<
padded_projection_funs,
deduce_result
filtered_pattern,
std::add_const,
std::add_lvalue_reference
>::type
padded_result_types;
base_signature;
typedef typename util::tl_zip<
typename util::tl_zip<
typename util::tl_map<
padded_result_types,
add_ref_if_not_void
>::type,
padded_signature,
util::left_or_right
>::type,
typename util::tl_map<
filtered_pattern,
add_const_ref
typedef typename util::tl_map_conditional<
typename util::tl_pad_left<
typename ctrait::arg_types,
filtered_pattern::size
>::type,
util::left_or_right
std::is_lvalue_reference,
false,
std::add_const,
std::add_lvalue_reference
>::type
projected_arg_types;
projection(fun_container const& args) : m_funs(args)
{
}
padded_expr_args;
projection(projection const&) = default;
/**
* @brief Invokes @p fun with a projection of <tt>args...</tt>.
*/
template<class PartialFun, typename... Args>
bool operator()(PartialFun& fun, Args&&... args) const
{
// can collect if ...
static constexpr bool can_collect =
// ... for each arg ...
util::tl_binary_forall<
util::type_list<Args...>,
typename util::tl_zip<
// ... args match conversion functions ...
// override base signature with required argument types of Expr
// and result types of transformation
typedef typename util::tl_zip<
typename util::tl_map<
padded_projection_funs,
deduce_unary_arg
padded_transformers,
util::get_result_type,
util::rm_option,
std::add_lvalue_reference
>::type,
// ... and reference types match
typename util::tl_zip<
padded_signature,
filtered_pattern,
deduce_ref_type
>::type,
padded_expr_args,
base_signature,
util::left_or_right
>::type,
std::is_convertible
>::value;
std::integral_constant<bool, can_collect> token;
return invoke(token, fun, std::forward<Args>(args)...);
}
private:
template<class PartialFun, typename... Args>
bool invoke(std::integral_constant<bool, false>,
PartialFun&, Args&&... ) const
{
return false;
}
util::left_or_right
>::type
partial_fun_signature;
template<class PartialFun, typename... Args>
bool invoke(std::integral_constant<bool, true>,
PartialFun& fun, Args&&... args ) const
{
// 'inherit' mutable references from partial_fun_signature
// for arguments without transformation
typedef typename util::tl_zip<
padded_result_types,
typename util::tl_map<
projected_arg_types,
gref_mutable_wrapped
typename util::tl_zip<
padded_transformers,
partial_fun_signature,
util::if_not_left
>::type,
util::left_or_right
base_signature,
util::deduce_ref_type
>::type
collected_arg_types;
typename detail::tdata_from_type_list<collected_arg_types>::type pargs;
if (collect(pargs, m_funs, std::forward<Args>(args)...))
{
projection_helper<PartialFun> helper{fun};
return util::unchecked_apply_tuple<bool>(helper, pargs);
}
return false;
}
template<typename Storage, typename T>
static inline bool fetch_(Storage& storage, T&& value)
{
storage = std::forward<T>(value);
return true;
}
template<class Storage>
static inline bool fetch_(Storage& storage, option<Storage>&& value)
{
if (value)
{
storage = std::move(*value);
return true;
}
return false;
}
template<class Storage, typename Fun, typename T>
static inline bool fetch(Storage& storage, Fun const& fun, T&& arg)
{
return fetch_(storage, fun(std::forward<T>(arg)));
}
template<typename Storage, typename T>
static inline bool fetch(Storage& storage, util::void_type const&, T&& arg)
{
return fetch_(storage, std::forward<T>(arg));
}
static inline bool collect(detail::tdata<>&, detail::tdata<> const&)
{
return true;
}
template<class TData, class Trans, typename T0, typename... Ts>
static inline bool collect(TData& td, Trans const& tr,
T0&& arg0, Ts&&... args)
{
return fetch(td.head, tr.head, std::forward<T0>(arg0))
&& collect(td.tail(), tr.tail(), std::forward<Ts>(args)...);
}
};
template<>
class projection<util::type_list<anything>, util::type_list<>, util::type_list<> >
{
public:
projection_signature;
template<typename... Args>
projection(Args const&...) { }
typedef util::type_list<anything> pattern_type;
typedef util::type_list<> projected_arg_types;
template<class PartialFun>
bool operator()(PartialFun& fun) const
{
fun();
return true;
}
};
typedef typename projection_from_type_list<
padded_transformers,
projection_signature
>::type
type1;
template<class Expr, class Guard, class Transformers, class Pattern>
struct get_cfl
{
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
partial_fun_signature
>::type
type2;
typedef std::pair<type1, type2> type;
typedef projection_partial_function_pair<Pattern, type1, type2> type;
};
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>
: std::is_same<typename First::second::pattern_type,
typename Second::second::pattern_type>
{
};
......@@ -695,13 +558,12 @@ struct invoke_helper
{
typedef typename Token::head type_pair;
typedef typename type_pair::second leaf_pair;
typedef typename leaf_pair::first_type projection_type;
if (*enabled++)
{
// next invocation step
invoke_helper2<Data,
Token,
typename projection_type::pattern_type> fun{data};
typename leaf_pair::pattern_type> fun{data};
return fun.invoke(std::forward<Args>(args)...);
}
//++enabled;
......@@ -720,9 +582,7 @@ struct can_invoke_helper
{
typedef typename Token::head type_pair;
typedef typename type_pair::second leaf_pair;
typedef typename leaf_pair::first_type projection_type;
typedef typename projection_type::pattern_type pattern_type;
typedef invoke_policy<pattern_type> impl;
typedef invoke_policy<typename leaf_pair::pattern_type> impl;
data[i++] = impl::can_invoke(std::forward<Args>(args)...);
}
};
......@@ -733,23 +593,6 @@ struct is_manipulator_leaf
static constexpr bool value = T::second_type::manipulates_args;
};
void collect_tdata(detail::tdata<>&)
{
}
template<typename Storage, typename... Args>
void collect_tdata(Storage& storage, detail::tdata<> const&, Args const&... args)
{
collect_tdata(storage, args...);
}
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...);
}
template<bool IsManipulator, typename T0, typename T1>
struct pj_fwd_
{
......@@ -817,15 +660,11 @@ class projected_fun
bool invoke(any_tuple const& tup)
{
if (has_manipulator)
return invoke(any_tuple{tup});
return _invoke(tup);
}
bool invoke(any_tuple& tup)
{
if (!has_manipulator)
return _invoke(static_cast<any_tuple const&>(tup));
return _invoke(tup);
}
......@@ -835,6 +674,22 @@ class projected_fun
return invoke(tmp);
}
template<typename... Args>
bool can_invoke(Args&&... args)
{
typedef detail::tdata<typename pj_fwd<has_manipulator, Args>::type...>
tuple_type;
// applies implicit conversions etc
tuple_type tup{std::forward<Args>(args)...};
auto& type_token = typeid(typename tuple_type::types);
eval_order token;
cache_entry tmp;
can_invoke_helper<cache_entry> fun{tmp};
util::static_foreach<0, eval_order::size>
::_(token, fun, type_token, tup);
return std::any_of(tmp.begin(), tmp.end(), [](bool value) { return value; });
}
template<typename... Args>
bool operator()(Args&&... args)
{
......@@ -970,17 +825,48 @@ class projected_fun
vals);
}
bool _invoke(any_tuple const& tup)
template<typename AnyTuple>
bool _invoke(AnyTuple& tup,
typename util::enable_if_c<
std::is_const<AnyTuple>::value == false
&& has_manipulator == true
>::type* = 0)
{
tup.force_detach();
auto& vals = *(tup.vals());
return _do_invoke(vals, vals.mutable_native_data());
}
template<typename AnyTuple>
bool _invoke(AnyTuple& tup,
typename util::enable_if_c<
std::is_const<AnyTuple>::value == false
&& has_manipulator == false
>::type* = 0)
{
return _invoke(static_cast<AnyTuple const&>(tup));
}
template<typename AnyTuple>
bool _invoke(AnyTuple& tup,
typename util::enable_if_c<
std::is_const<AnyTuple>::value == true
&& has_manipulator == false
>::type* = 0)
{
auto const& cvals = *(tup.cvals());
return _do_invoke(cvals, cvals.native_data());
}
bool _invoke(any_tuple& tup)
template<typename AnyTuple>
bool _invoke(AnyTuple& tup,
typename util::enable_if_c<
std::is_const<AnyTuple>::value == true
&& has_manipulator == true
>::type* = 0)
{
tup.force_detach();
auto& vals = *(tup.vals());
return _do_invoke(vals, vals.mutable_native_data());
any_tuple tup_copy{tup};
return _invoke(tup_copy);
}
};
......@@ -1026,73 +912,6 @@ pj_concat(Arg0 const& arg0, Args const&... args)
#define VERBOSE(LineOfCode) cout << #LineOfCode << " = " << (LineOfCode) << endl
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 _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...);
}
};
typedef value_guard< util::type_list<> > dummy_guard;
struct cf_builder_from_args { };
......@@ -1138,7 +957,7 @@ struct cf_builder
when(NewGuard ng,
typename util::disable_if_c<
std::is_same<NewGuard, NewGuard>::value
&& std::is_same<Guard, dummy_guard>::value
&& std::is_same<Guard, value_guard< util::type_list<> >>::value
>::type* = 0 ) const
{
return {(gcall(m_guard) && ng), m_funs};
......@@ -1149,7 +968,7 @@ struct cf_builder
when(NewGuard ng,
typename util::enable_if_c<
std::is_same<NewGuard, NewGuard>::value
&& std::is_same<Guard, dummy_guard>::value
&& std::is_same<Guard, value_guard< util::type_list<> >>::value
>::type* = 0 ) const
{
return {ng, m_funs};
......@@ -1166,14 +985,6 @@ struct cf_builder
};
template<typename... T>
cf_builder<value_guard<util::type_list<> >,
util::type_list<>,
util::type_list<T...> > _on()
{
return {};
}
template<bool IsFun, typename T>
struct add_ptr_to_fun_
{
......@@ -1233,6 +1044,15 @@ struct pattern_type : pattern_type_<util::is_callable<T>::value && !detail::is_b
{
};
template<typename... T>
cf_builder<value_guard<util::type_list<> >,
util::type_list<>,
util::type_list<T...> >
_on()
{
return {};
}
template<typename Arg0, typename... Args>
cf_builder<
value_guard<
......@@ -1240,8 +1060,7 @@ cf_builder<
typename util::tl_map<
util::type_list<Arg0, Args...>,
boxed_and_callable_to_void
>::type,
util::void_type
>::type
>::type
>,
typename util::tl_map<
......@@ -1461,6 +1280,53 @@ size_t test__tuple()
CPPA_CHECK(f11("10"));
CPPA_CHECK_EQUAL(10, f11_fun);
auto f12 = pj_concat
(
_on<int, anything, int>().when(_x1 < _x2) >> [&](int a, int b)
{
CPPA_CHECK_EQUAL(1, a);
CPPA_CHECK_EQUAL(5, b);
invoked = "f12";
}
);
CPPA_CHECK_INVOKED(f12, (1, 2, 3, 4, 5));
int f13_fun = 0;
auto f13 = pj_concat
(
_on<int, anything, std::string, anything, int>().when(_x1 < _x3 && _x2.starts_with("-")) >> [&](int a, std::string const& str, int b)
{
CPPA_CHECK_EQUAL("-h", str);
CPPA_CHECK_EQUAL(1, a);
CPPA_CHECK_EQUAL(10, b);
f13_fun = 1;
invoked = "f13";
},
_on<anything, std::string, anything, int, anything, float, anything>() >> [&](std::string const& str, int a, float b)
{
CPPA_CHECK_EQUAL("h", str);
CPPA_CHECK_EQUAL(12, a);
CPPA_CHECK_EQUAL(1.f, b);
f13_fun = 2;
invoked = "f13";
},
_on<float, anything, float>().when(_x1 * 2 == _x2) >> [&](float a, float b)
{
CPPA_CHECK_EQUAL(1.f, a);
CPPA_CHECK_EQUAL(2.f, b);
f13_fun = 3;
invoked = "f13";
}
);
CPPA_CHECK_INVOKED(f13, (1, 2, "-h", 12, 32, 10, 1.f, "--foo", 10));
CPPA_CHECK_EQUAL(1, f13_fun);
CPPA_CHECK_INVOKED(f13, (1, 2, "h", 12, 32, 10, 1.f, "--foo", 10));
CPPA_CHECK_EQUAL(2, f13_fun);
CPPA_CHECK_INVOKED(f13, (1.f, 1.5f, 2.f));
CPPA_CHECK_EQUAL(3, f13_fun);
//exit(0);
return CPPA_TEST_RESULT;
auto old_pf =
......@@ -1642,8 +1508,8 @@ size_t test__tuple()
//.or_else(f00)
.or_else(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{}))
.or_else(cfun<token1>([](int, int) { cout << "f0[4]" << endl; }, dummy_guard{}));
.or_else(cfun<token2>([](float) { cout << "f0[3]!" << endl; }, value_guard< util::type_list<> >{}))
.or_else(cfun<token1>([](int, int) { cout << "f0[4]" << endl; }, value_guard< util::type_list<> >{}));
//VERBOSE(f0(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