Commit d3d55a4c authored by neverlord's avatar neverlord

pattern matching

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