Commit 704aa400 authored by Dominik Charousset's avatar Dominik Charousset

maintenance

parent 7ae2965f
...@@ -61,3 +61,4 @@ examples/announce_example_5 ...@@ -61,3 +61,4 @@ examples/announce_example_5
examples/hello_world_example examples/hello_world_example
examples/math_actor_example examples/math_actor_example
examples/dining_philosophers examples/dining_philosophers
examples/dancing_kirby
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef ANY_TUPLE_HPP #ifndef ANY_TUPLE_HPP
#define ANY_TUPLE_HPP #define ANY_TUPLE_HPP
#include <iostream>
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/cow_ptr.hpp" #include "cppa/cow_ptr.hpp"
...@@ -136,7 +138,7 @@ class any_tuple ...@@ -136,7 +138,7 @@ class any_tuple
} }
template<typename T> template<typename T>
inline T& get_mutable_as(size_t p) inline T& get_as_mutable(size_t p)
{ {
CPPA_REQUIRE(*(type_at(p)) == typeid(T)); CPPA_REQUIRE(*(type_at(p)) == typeid(T));
return *reinterpret_cast<T*>(mutable_at(p)); return *reinterpret_cast<T*>(mutable_at(p));
...@@ -146,14 +148,16 @@ class any_tuple ...@@ -146,14 +148,16 @@ class any_tuple
inline const_iterator end() const { return m_vals->end(); } inline const_iterator end() const { return m_vals->end(); }
cow_ptr<detail::abstract_tuple> const& vals() const; inline cow_ptr<detail::abstract_tuple>& vals() { return m_vals; }
inline cow_ptr<detail::abstract_tuple> const& vals() const { return m_vals; }
inline cow_ptr<detail::abstract_tuple> const& cvals() const { return m_vals; }
inline void const* type_token() const inline std::type_info const* type_token() const
{ {
return m_vals->type_token(); return m_vals->type_token();
} }
inline std::type_info const* impl_type() const inline detail::tuple_impl_info impl_type() const
{ {
return m_vals->impl_type(); return m_vals->impl_type();
} }
...@@ -235,7 +239,7 @@ class any_tuple ...@@ -235,7 +239,7 @@ class any_tuple
std::integral_constant<bool, false>) std::integral_constant<bool, false>)
{ {
typedef typename util::rm_ref<T>::type ctype; typedef typename util::rm_ref<T>::type ctype;
return new detail::container_tuple_view<T>(new ctype(std::forward<T>(value))); return new detail::container_tuple_view<T>(new ctype(std::forward<T>(value)), true);
} }
}; };
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#define ABSTRACT_TUPLE_HPP #define ABSTRACT_TUPLE_HPP
#include <iterator> #include <iterator>
#include <typeinfo>
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/ref_counted.hpp" #include "cppa/ref_counted.hpp"
...@@ -42,11 +43,21 @@ ...@@ -42,11 +43,21 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
struct abstract_tuple : ref_counted enum tuple_impl_info
{ {
statically_typed,
dynamically_typed
};
class abstract_tuple : public ref_counted
{
tuple_impl_info m_impl_type;
public:
abstract_tuple() = default; inline abstract_tuple(tuple_impl_info tii) : m_impl_type(tii) { }
abstract_tuple(abstract_tuple const&); abstract_tuple(abstract_tuple const& other);
// mutators // mutators
virtual void* mutable_at(size_t pos) = 0; virtual void* mutable_at(size_t pos) = 0;
...@@ -57,12 +68,16 @@ struct abstract_tuple : ref_counted ...@@ -57,12 +68,16 @@ struct abstract_tuple : ref_counted
virtual void const* at(size_t pos) const = 0; virtual void const* at(size_t pos) const = 0;
virtual uniform_type_info const* type_at(size_t pos) const = 0; virtual uniform_type_info const* type_at(size_t pos) const = 0;
// identifies the type of the implementation, this is NOT the // Identifies the type of the implementation.
// typeid of the implementation class // A statically typed tuple implementation can use some optimizations,
virtual std::type_info const* impl_type() const = 0; // e.g., "impl_type() == statically_typed" implies that type_token()
// identifies all possible instances of a given tuple implementation
inline tuple_impl_info impl_type() const { return m_impl_type; }
// uniquely identifies this category (element types) of messages // uniquely identifies this category (element types) of messages
virtual void const* type_token() const = 0; // override this member function only if impl_type() == statically_typed
// (default returns &typeid(void))
virtual std::type_info const* type_token() const;
bool equals(abstract_tuple const& other) const; bool equals(abstract_tuple const& other) const;
...@@ -151,8 +166,10 @@ struct abstract_tuple : ref_counted ...@@ -151,8 +166,10 @@ struct abstract_tuple : ref_counted
}; };
inline const_iterator begin() const { return {this}; } 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 end() const { return {this, size()}; }
inline const_iterator cend() const { return {this, size()}; }
}; };
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
#ifndef CONTAINER_TUPLE_VIEW_HPP #ifndef CONTAINER_TUPLE_VIEW_HPP
#define CONTAINER_TUPLE_VIEW_HPP #define CONTAINER_TUPLE_VIEW_HPP
#include <iostream>
#include "cppa/detail/tuple_vals.hpp" #include "cppa/detail/tuple_vals.hpp"
#include "cppa/detail/object_array.hpp" #include "cppa/detail/object_array.hpp"
#include "cppa/detail/abstract_tuple.hpp" #include "cppa/detail/abstract_tuple.hpp"
...@@ -42,11 +44,14 @@ template<class Container> ...@@ -42,11 +44,14 @@ template<class Container>
class container_tuple_view : public abstract_tuple class container_tuple_view : public abstract_tuple
{ {
typedef abstract_tuple super;
public: public:
typedef typename Container::value_type value_type; typedef typename Container::value_type value_type;
container_tuple_view(Container* c, bool take_ownership = false) : m_ptr(c) container_tuple_view(Container* c, bool take_ownership = false)
: super(tuple_impl_info::dynamically_typed), m_ptr(c)
{ {
CPPA_REQUIRE(c != nullptr); CPPA_REQUIRE(c != nullptr);
if (!take_ownership) m_ptr.get_deleter().disable(); if (!take_ownership) m_ptr.get_deleter().disable();
...@@ -78,22 +83,11 @@ class container_tuple_view : public abstract_tuple ...@@ -78,22 +83,11 @@ class container_tuple_view : public abstract_tuple
return &(*i); return &(*i);
} }
uniform_type_info const* type_at(size_t pos) const uniform_type_info const* type_at(size_t) const
{ {
CPPA_REQUIRE(pos < size());
return static_types_array<value_type>::arr[0]; return static_types_array<value_type>::arr[0];
} }
void const* type_token() const
{
return &(typeid(Container));
}
std::type_info const* impl_type() const
{
return &(typeid(detail::object_array));
}
private: private:
std::unique_ptr<Container, disablable_delete<Container> > m_ptr; std::unique_ptr<Container, disablable_delete<Container> > m_ptr;
......
...@@ -53,6 +53,8 @@ template<typename... ElementTypes> ...@@ -53,6 +53,8 @@ template<typename... ElementTypes>
class decorated_tuple : public abstract_tuple class decorated_tuple : public abstract_tuple
{ {
typedef abstract_tuple super;
static_assert(sizeof...(ElementTypes) > 0, static_assert(sizeof...(ElementTypes) > 0,
"decorated_tuple is not allowed to be empty"); "decorated_tuple is not allowed to be empty");
...@@ -102,14 +104,9 @@ class decorated_tuple : public abstract_tuple ...@@ -102,14 +104,9 @@ class decorated_tuple : public abstract_tuple
return m_decorated->type_at(m_mapping[pos]); return m_decorated->type_at(m_mapping[pos]);
} }
void const* type_token() const std::type_info const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
std::type_info const* impl_type() const
{ {
return detail::static_type_list<ElementTypes...>::list; return static_type_list<ElementTypes...>::list;
} }
private: private:
...@@ -118,7 +115,8 @@ class decorated_tuple : public abstract_tuple ...@@ -118,7 +115,8 @@ class decorated_tuple : public abstract_tuple
vector_type m_mapping; vector_type m_mapping;
decorated_tuple(cow_pointer_type d, vector_type const& v) decorated_tuple(cow_pointer_type d, vector_type const& v)
: m_decorated(std::move(d)), m_mapping(v) : super(tuple_impl_info::statically_typed)
, m_decorated(std::move(d)), m_mapping(v)
{ {
# ifdef CPPA_DEBUG # ifdef CPPA_DEBUG
cow_pointer_type const& ptr = m_decorated; // prevent detaching cow_pointer_type const& ptr = m_decorated; // prevent detaching
...@@ -129,7 +127,7 @@ class decorated_tuple : public abstract_tuple ...@@ -129,7 +127,7 @@ class decorated_tuple : public abstract_tuple
} }
decorated_tuple(cow_pointer_type d, size_t offset) decorated_tuple(cow_pointer_type d, size_t offset)
: m_decorated(std::move(d)) : super(tuple_impl_info::statically_typed), m_decorated(std::move(d))
{ {
# ifdef CPPA_DEBUG # ifdef CPPA_DEBUG
cow_pointer_type const& ptr = m_decorated; // prevent detaching cow_pointer_type const& ptr = m_decorated; // prevent detaching
......
...@@ -40,14 +40,14 @@ struct empty_tuple : abstract_tuple ...@@ -40,14 +40,14 @@ struct empty_tuple : abstract_tuple
using abstract_tuple::const_iterator; using abstract_tuple::const_iterator;
empty_tuple();
size_t size() const; size_t size() const;
void* mutable_at(size_t); void* mutable_at(size_t);
abstract_tuple* copy() const; abstract_tuple* copy() const;
void const* at(size_t) const; void const* at(size_t) const;
bool equals(abstract_tuple const& other) const; bool equals(abstract_tuple const& other) const;
uniform_type_info const* type_at(size_t) const; uniform_type_info const* type_at(size_t) const;
std::type_info const* impl_type() const; std::type_info const* type_token() const;
void const* type_token() const;
}; };
......
...@@ -47,9 +47,6 @@ ...@@ -47,9 +47,6 @@
#include "cppa/detail/matches.hpp" #include "cppa/detail/matches.hpp"
#include "cppa/detail/intermediate.hpp" #include "cppa/detail/intermediate.hpp"
// forward declaration
namespace cppa { class any_tuple; class partial_function; }
namespace cppa { namespace detail { namespace cppa { namespace detail {
class invokable class invokable
...@@ -65,207 +62,306 @@ class invokable ...@@ -65,207 +62,306 @@ class invokable
inline invokable() : next(nullptr) { } inline invokable() : next(nullptr) { }
virtual ~invokable(); virtual ~invokable();
virtual bool invoke(any_tuple const&) const;
// Suppress type checking.
virtual bool unsafe_invoke(any_tuple const& value) const;
// Checks whether the types of @p value match the pattern. // Checks whether the types of @p value match the pattern.
virtual bool types_match(any_tuple const& value) const; virtual bool types_match(any_tuple const& value) const;
// Checks whether this invokable could be invoked with @p value. // Checks whether this invokable could be invoked with @p value.
virtual bool could_invoke(any_tuple const& value) const; virtual bool could_invoke(any_tuple const& value) const;
// Type checking.
virtual bool invoke(any_tuple& value) const;
// Suppress type checking.
virtual bool unsafe_invoke(any_tuple& value) const;
// Prepare this invokable. // Prepare this invokable.
virtual intermediate* get_intermediate(any_tuple const& value); virtual intermediate* get_intermediate(any_tuple& value);
// Prepare this invokable and suppress type checking. // Prepare this invokable and suppress type checking.
virtual intermediate* get_unsafe_intermediate(any_tuple const& value); virtual intermediate* get_unsafe_intermediate(any_tuple& value);
}; };
template<class Tuple, class Pattern> /*
struct abstract_invokable : public invokable * @tparam Fun Function or functor
* @tparam FunArgs Type list of functor parameters *without* any qualifiers
*/
template<typename Fun, class FunArgs, class TupleTypes>
struct iimpl : intermediate
{ {
Pattern m_pattern; typedef Fun functor_type;
abstract_invokable() { } typedef typename tuple_from_type_list<TupleTypes>::type tuple_type;
template<typename... Args> functor_type m_fun;
abstract_invokable(Args&&... args) : m_pattern(std::forward<Args>(args)...) tuple_type m_default_args;
tuple_type m_args;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
void invoke()
{ {
util::apply_tuple(m_fun, m_args);
// "forget" arguments after invocation
m_args = m_default_args;
} }
bool types_match(any_tuple const& value) const inline intermediate* prepare(option<tuple_type>&& tup)
{ {
return matches_types(value, m_pattern); if (tup)
} {
bool could_invoke(any_tuple const& value) const m_args = std::move(*tup);
{ return this;
return matches(value, m_pattern); }
return nullptr;
} }
}; inline bool operator()(option<tuple_type>&& tup) const
template<bool CheckValues, size_t NumArgs, typename Fun, class Tuple, class Pattern>
class invokable_impl : public abstract_invokable<Tuple, Pattern>
{
typedef abstract_invokable<Tuple, Pattern> super;
template<typename T>
inline bool invoke_impl(option<T>&& tup) const
{ {
if (tup) if (tup)
{ {
util::apply_tuple(m_iimpl.m_fun, *tup); util::apply_tuple(m_fun, *tup);
return true; return true;
} }
return false; return false;
} }
};
template<typename T> template<typename Fun, class TupleTypes>
inline intermediate* get_intermediate_impl(option<T>&& tup) struct iimpl<Fun, util::type_list<>, TupleTypes> : intermediate
{
typedef Fun functor_type;
functor_type m_fun;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
void invoke() { m_fun(); }
inline intermediate* prepare(bool result) // result passed by policy
{ {
if (tup) return result ? this : nullptr;
{
m_iimpl.m_args = std::move(*tup);
return &m_iimpl;
}
return nullptr;
} }
inline bool operator()(bool result) const // result passed by policy
{
if (result) m_fun();
return result;
}
};
protected: template<typename Fun, class TupleTypes>
struct iimpl<Fun, util::type_list<any_tuple>, TupleTypes> : intermediate
struct iimpl : intermediate {
typedef Fun functor_type;
functor_type m_fun;
any_tuple m_arg;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
void invoke() { m_fun(m_arg); m_arg = any_tuple{}; }
inline intermediate* prepare(any_tuple arg)
{
m_arg = std::move(arg);
return this;
}
inline bool operator()(any_tuple arg) const
{ {
Fun m_fun; m_fun(arg);
Tuple m_args; return true;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
void invoke() { util::apply_tuple(m_fun, m_args); }
} }
m_iimpl; };
public: enum mapping_policy
{
do_not_map,
map_to_bool,
map_to_option
};
template<typename F, typename... Args> template<mapping_policy, class Pattern>
invokable_impl(F&& fun, Args&&... args) struct pattern_policy
: super(std::forward<Args>(args)...), m_iimpl(std::forward<F>(fun)) {
Pattern m_pattern;
template<typename... Args>
pattern_policy(Args&&... args) : m_pattern(std::forward<Args>(args)...) { }
bool types_match(any_tuple const& value) const
{ {
return matches_types(value, m_pattern);
} }
bool could_invoke(any_tuple const& value) const
bool invoke(any_tuple const& value) const
{ {
return invoke_impl(tuple_cast(value, this->m_pattern)); return matches(value, m_pattern);
} }
any_tuple map(any_tuple& value) const
bool unsafe_invoke(any_tuple const& value) const
{ {
return invoke_impl(unsafe_tuple_cast(value, this->m_pattern)); return std::move(value);
} }
any_tuple map_unsafe(any_tuple& value) const
intermediate* get_intermediate(any_tuple const& value)
{ {
return get_intermediate_impl(tuple_cast(value, this->m_pattern)); return std::move(value);
} }
};
intermediate* get_unsafe_intermediate(any_tuple const& value) template<class Pattern>
struct pattern_policy<map_to_option, Pattern>
{
Pattern m_pattern;
template<typename... Args>
pattern_policy(Args&&... args) : m_pattern(std::forward<Args>(args)...) { }
bool types_match(any_tuple const& value) const
{ {
return get_intermediate_impl(unsafe_tuple_cast(value, this->m_pattern)); return matches_types(value, m_pattern);
}
bool could_invoke(any_tuple const& value) const
{
return matches(value, m_pattern);
}
auto map(any_tuple& value) const
-> decltype(moving_tuple_cast(value, m_pattern))
{
auto result = moving_tuple_cast(value, m_pattern);
return result;
} }
auto map_unsafe(any_tuple& value) const
-> decltype(unsafe_tuple_cast(value, m_pattern))
{
return unsafe_tuple_cast(value, m_pattern);
}
};
template<class Pattern>
struct pattern_policy<map_to_bool, Pattern>
{
Pattern m_pattern;
template<typename... Args>
pattern_policy(Args&&... args) : m_pattern(std::forward<Args>(args)...) { }
bool types_match(any_tuple const& value) const
{
return matches_types(value, m_pattern);
}
bool could_invoke(any_tuple const& value) const
{
return matches(value, m_pattern);
}
bool map(any_tuple& value) const
{
return could_invoke(value);
}
bool map_unsafe(any_tuple& value) const
{
return could_invoke(value);
}
}; };
template<size_t NumArgs, typename Fun, class Tuple, class Pattern> struct dummy_policy
struct invokable_impl<false, NumArgs, Fun, Tuple, Pattern> : public invokable_impl<true, NumArgs, Fun, Tuple, Pattern>
{ {
typedef invokable_impl<true, NumArgs, Fun, Tuple, Pattern> super; inline bool types_match(any_tuple const&) const
template<typename F>
invokable_impl(F&& fun) : super(std::forward<F>(fun))
{ {
return true;
} }
bool unsafe_invoke(any_tuple const& value) const inline bool could_invoke(any_tuple const&) const
{ {
auto tup = forced_tuple_cast(value, this->m_pattern);
util::apply_tuple((this->m_iimpl).m_fun, tup);
return true; return true;
} }
intermediate* get_unsafe_intermediate(any_tuple const& value) inline any_tuple map(any_tuple& value) const
{
return std::move(value);
}
inline any_tuple map_unsafe(any_tuple& value) const
{ {
(this->m_iimpl).m_args = forced_tuple_cast(value, this->m_pattern); return std::move(value);
return &(this->m_iimpl);
} }
}; };
template<typename Fun, class Tuple, class Pattern> template<class IntermediateImpl, class Policy>
class invokable_impl<true, 0, Fun, Tuple, Pattern> : public abstract_invokable<Tuple, Pattern> struct invokable_impl : public invokable
{ {
typedef abstract_invokable<Tuple, Pattern> super; IntermediateImpl m_ii;
Policy m_policy;
template<typename... P> template<typename Arg0, typename... Args>
inline bool unsafe_vmatch(any_tuple const& t, pattern<P...> const& p) const invokable_impl(Arg0&& arg0, Args&&... args)
: m_ii(std::forward<Arg0>(arg0))
, m_policy(std::forward<Args>(args)...)
{ {
return matcher<pattern<P...>::wildcard_pos, P...>::vmatch(t, p);
} }
protected: bool invoke(any_tuple& value) const
struct iimpl : intermediate
{ {
Fun m_fun; return m_ii(m_policy.map(value));
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
void invoke() { m_fun(); }
inline bool operator()() const { m_fun(); return true; }
} }
m_iimpl;
public:
template<typename F, typename... Args> bool unsafe_invoke(any_tuple& value) const
invokable_impl(F&& fun, Args&&... args)
: super(std::forward<Args>(args)...), m_iimpl(std::forward<F>(fun))
{ {
return m_ii(m_policy.map_unsafe(value));
} }
bool invoke(any_tuple const& value) const
bool types_match(any_tuple const& value) const
{ {
return matches(value, this->m_pattern) ? m_iimpl() : false; return m_policy.types_match(value);
} }
bool unsafe_invoke(any_tuple const& value) const
bool could_invoke(any_tuple const& value) const
{ {
return unsafe_vmatch(value, this->m_pattern) ? m_iimpl() : false; return m_policy.could_invoke(value);
} }
intermediate* get_intermediate(any_tuple const& value)
intermediate* get_intermediate(any_tuple& value)
{ {
return matches(value, this->m_pattern) ? &m_iimpl : nullptr; return m_ii.prepare(m_policy.map(value));
} }
intermediate* get_unsafe_intermediate(any_tuple const& value)
intermediate* get_unsafe_intermediate(any_tuple& value)
{ {
return unsafe_vmatch(value, this->m_pattern) ? &m_iimpl : nullptr; return m_ii.prepare(m_policy.map_unsafe(value));
} }
}; };
template<typename Fun, class Tuple, class Pattern> template<class ArgTypes>
struct invokable_impl<false, 0, Fun, Tuple, Pattern> : public invokable_impl<true, 0, Fun, Tuple, Pattern> constexpr mapping_policy get_mapping_policy()
{ {
typedef invokable_impl<true, 0, Fun, Tuple, Pattern> super; return (ArgTypes::size == 0)
template<typename... Args> ? map_to_bool
invokable_impl(Args&&... args) : super(std::forward<Args>(args)...) { } : (( std::is_same<typename ArgTypes::head, any_tuple>::value
bool unsafe_invoke(any_tuple const&) const && ArgTypes::size == 1)
{ ? do_not_map
return (this->m_iimpl)(); : map_to_option);
} }
intermediate* get_unsafe_intermediate(any_tuple const&)
{ template<class Container>
return &(this->m_iimpl); struct filtered;
}
template<typename... Ts>
struct filtered<util::type_list<Ts...> >
{
typedef typename util::tl_filter_not<util::type_list<Ts...>, is_anything>::type
types;
}; };
template<typename... Ts>
struct filtered<pattern<Ts...> >
{
typedef typename filtered<util::type_list<Ts...>>::types types;
};
template<typename Fun, class Pattern> template<typename Fun, class Pattern>
struct select_invokable_impl struct select_invokable_impl
{ {
typedef typename util::get_arg_types<Fun>::types arg_types; typedef typename util::get_arg_types<Fun>::types qualified_arg_types;
typedef typename Pattern::filtered_types filtered_types; typedef typename util::tl_apply<qualified_arg_types, util::rm_ref>::type
typedef typename tuple_from_type_list<filtered_types>::type tuple_type; arg_types;
typedef invokable_impl<true, arg_types::size, Fun, tuple_type, Pattern> type1; static constexpr mapping_policy mp = get_mapping_policy<arg_types>();
typedef invokable_impl<false, arg_types::size, Fun, tuple_type, Pattern> type2; typedef invokable_impl<iimpl<Fun, arg_types, typename filtered<Pattern>::types>,
pattern_policy<mp, Pattern> > type;
};
template<typename Fun>
struct select_invokable_impl<Fun, pattern<anything> >
{
typedef typename util::get_arg_types<Fun>::types qualified_arg_types;
typedef typename util::tl_apply<qualified_arg_types, util::rm_ref>::type
arg_types;
typedef typename util::rm_ref<typename arg_types::head>::type arg0;
static_assert(arg_types::size < 2, "functor has too many arguments");
static_assert( arg_types::size == 0
|| std::is_same<any_tuple, arg0>::value,
"bad signature");
typedef invokable_impl<iimpl<Fun, arg_types, util::type_list<> >,
dummy_policy> type;
}; };
template<class Pattern, typename Fun, typename Data> template<class Pattern, typename Fun, typename Data>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, Data&& dt) std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, Data&& dt)
{ {
typedef typename select_invokable_impl<Fun, Pattern>::type1 result; typedef typename select_invokable_impl<Fun, Pattern>::type result;
return std::unique_ptr<invokable>( return std::unique_ptr<invokable>(
new result(std::forward<Fun>(fun), std::forward<Data>(dt))); new result(std::forward<Fun>(fun), std::forward<Data>(dt)));
} }
...@@ -273,7 +369,7 @@ std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, Data&& dt) ...@@ -273,7 +369,7 @@ std::unique_ptr<invokable> get_invokable_impl(Fun&& fun, Data&& dt)
template<class Pattern, typename Fun> template<class Pattern, typename Fun>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun) std::unique_ptr<invokable> get_invokable_impl(Fun&& fun)
{ {
typedef typename select_invokable_impl<Fun, Pattern>::type2 result; typedef typename select_invokable_impl<Fun, typename Pattern::types>::type result;
return std::unique_ptr<invokable>(new result(std::forward<Fun>(fun))); return std::unique_ptr<invokable>(new result(std::forward<Fun>(fun)));
} }
......
...@@ -46,18 +46,14 @@ struct matcher<wildcard_position::nil, T...> ...@@ -46,18 +46,14 @@ struct matcher<wildcard_position::nil, T...>
{ {
static inline bool tmatch(any_tuple const& tup) static inline bool tmatch(any_tuple const& tup)
{ {
// match implementation type if possible if (tup.impl_type() == tuple_impl_info::statically_typed)
auto impl = tup.impl_type();
// the impl_type of both decorated_tuple and tuple_vals
// is &typeid(type_list<T...>)
auto tinf = detail::static_type_list<T...>::list;
if (impl == tinf || *impl == *tinf)
{ {
return true; // statically typed tuples return &typeid(type_list<T...>)
// as type token
return typeid(util::type_list<T...>) == *(tup.type_token());
} }
// always use a full dynamic match for object arrays // always use a full dynamic match for dynamic typed tuples
else if (*impl == typeid(detail::object_array) else if (tup.size() == sizeof...(T))
&& tup.size() == sizeof...(T))
{ {
auto& tarr = detail::static_types_array<T...>::arr; auto& tarr = detail::static_types_array<T...>::arr;
return std::equal(tup.begin(), tup.end(), tarr.begin(), return std::equal(tup.begin(), tup.end(), tarr.begin(),
...@@ -479,6 +475,24 @@ bool matches(any_tuple const& tup, pattern<Ts...> const& pn, ...@@ -479,6 +475,24 @@ bool matches(any_tuple const& tup, pattern<Ts...> const& pn,
mv); mv);
} }
// support for type_list based matching
template<typename... Ts>
inline bool matches(any_tuple const& tup, util::type_list<Ts...> const&)
{
return matches<Ts...>(tup);
}
template<typename... Ts>
inline bool matches(any_tuple const& tup, util::type_list<Ts...> const&,
util::fixed_vector<
size_t,
util::tl_count_not<
util::type_list<Ts...>,
is_anything>::value>& mv)
{
return matches<Ts...>(mv);
}
/* /*
* @brief Returns true if this tuple matches the pattern <tt>{Ts...}</tt> * @brief Returns true if this tuple matches the pattern <tt>{Ts...}</tt>
* (does not match for values). * (does not match for values).
...@@ -489,6 +503,12 @@ inline bool matches_types(any_tuple const& tup, pattern<Ts...> const&) ...@@ -489,6 +503,12 @@ inline bool matches_types(any_tuple const& tup, pattern<Ts...> const&)
return matches<Ts...>(tup); return matches<Ts...>(tup);
} }
template<typename... Ts>
inline bool matches_types(any_tuple const& tup, util::type_list<Ts...> const&)
{
return matches<Ts...>(tup);
}
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // MATCHES_HPP #endif // MATCHES_HPP
...@@ -42,13 +42,13 @@ namespace cppa { namespace detail { ...@@ -42,13 +42,13 @@ namespace cppa { namespace detail {
class object_array : public abstract_tuple class object_array : public abstract_tuple
{ {
std::vector<object> m_elements; typedef abstract_tuple super;
public: public:
using abstract_tuple::const_iterator; using abstract_tuple::const_iterator;
object_array() = default; object_array();
object_array(object_array&&) = default; object_array(object_array&&) = default;
object_array(object_array const&) = default; object_array(object_array const&) = default;
...@@ -68,9 +68,9 @@ class object_array : public abstract_tuple ...@@ -68,9 +68,9 @@ class object_array : public abstract_tuple
uniform_type_info const* type_at(size_t pos) const; uniform_type_info const* type_at(size_t pos) const;
void const* type_token() const; private:
std::type_info const* impl_type() const; std::vector<object> m_elements;
}; };
......
...@@ -61,19 +61,21 @@ struct tuple_cast_impl ...@@ -61,19 +61,21 @@ struct tuple_cast_impl
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 const& tup) static inline option<Result> safe(any_tuple& tup)
{ {
mapping_vector mv; mapping_vector mv;
if (matches<T...>(tup, mv)) return {Result::from(tup.vals(), mv)}; if (matches<T...>(tup, mv)) return {Result::from(std::move(tup.vals()),
mv)};
return {}; return {};
} }
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p) static inline option<Result> safe(any_tuple& tup, pattern<T...> const& p)
{ {
mapping_vector mv; mapping_vector mv;
if (matches(tup, p, mv)) return {Result::from(tup.vals(), mv)}; if (matches(tup, p, mv)) return {Result::from(std::move(tup.vals()),
mv)};
return {}; return {};
} }
static inline option<Result> unsafe(any_tuple const& tup, pattern<T...> const& p) static inline option<Result> unsafe(any_tuple& tup, pattern<T...> const& p)
{ {
mapping_vector mv; mapping_vector mv;
if (WP == wildcard_position::in_between) if (WP == wildcard_position::in_between)
...@@ -87,16 +89,17 @@ struct tuple_cast_impl ...@@ -87,16 +89,17 @@ struct tuple_cast_impl
// second range // second range
begin = mv.begin() + first_wc; begin = mv.begin() + first_wc;
std::iota(begin, mv.end(), tup.size() - (size - first_wc)); std::iota(begin, mv.end(), tup.size() - (size - first_wc));
return {Result::from(tup.vals(), mv)}; return {Result::from(std::move(tup.vals()), mv)};
} }
} }
else else
{ {
if (matches(tup, p, mv)) return {Result::from(tup.vals(), mv)}; if (matches(tup, p, mv)) return {Result::from(std::move(tup.vals()),
mv)};
} }
return {}; return {};
} }
static inline Result force(any_tuple const& tup, pattern<T...> const& p) static inline Result force(any_tuple& tup, pattern<T...> const& p)
{ {
mapping_vector mv; mapping_vector mv;
if (WP == wildcard_position::in_between) if (WP == wildcard_position::in_between)
...@@ -108,12 +111,12 @@ struct tuple_cast_impl ...@@ -108,12 +111,12 @@ struct tuple_cast_impl
// second range // second range
begin = mv.begin() + first_wc; begin = mv.begin() + first_wc;
std::iota(begin, mv.end(), tup.size() - (size - first_wc)); std::iota(begin, mv.end(), tup.size() - (size - first_wc));
return {Result::from(tup.vals(), mv)}; return {Result::from(std::move(tup.vals()), mv)};
} }
else else
{ {
matches(tup, p, mv); matches(tup, p, mv);
return {Result::from(tup.vals(), mv)}; return {Result::from(std::move(tup.vals()), mv)};
} }
} }
}; };
...@@ -121,28 +124,31 @@ struct tuple_cast_impl ...@@ -121,28 +124,31 @@ struct tuple_cast_impl
template<class Result, typename... T> template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::nil, Result, T...> struct tuple_cast_impl<wildcard_position::nil, Result, T...>
{ {
static inline option<Result> safe(any_tuple const& tup) static inline option<Result> safe(any_tuple& tup)
{ {
if (matches<T...>(tup)) return {Result::from(tup.vals())}; if (matches<T...>(tup)) return {Result::from(std::move(tup.vals()))};
return {}; return {};
} }
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p) static inline option<Result> safe(any_tuple& tup, pattern<T...> const& p)
{ {
if (matches(tup, p)) return {Result::from(tup.vals())}; if (matches(tup, p))
{
return {Result::from(std::move(tup.vals()))};
}
return {}; return {};
} }
static inline option<Result> unsafe(any_tuple const& 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, T...>::vmatch(tup, p))
{ {
return {Result::from(tup.vals())}; return {Result::from(std::move(tup.vals()))};
} }
return {}; return {};
} }
static inline Result force(any_tuple const& tup, pattern<T...> const&) static inline Result force(any_tuple& tup, pattern<T...> const&)
{ {
return {Result::from(tup.vals())}; return {Result::from(std::move(tup.vals()))};
} }
}; };
...@@ -150,37 +156,37 @@ template<class Result, typename... T> ...@@ -150,37 +156,37 @@ template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::trailing, Result, T...> struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
: tuple_cast_impl<wildcard_position::nil, Result, T...> : tuple_cast_impl<wildcard_position::nil, Result, T...>
{ {
static inline option<Result> unsafe(any_tuple const& 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, T...>::vmatch(tup, p))
{ {
return {Result::from(tup.vals())}; return {Result::from(std::move(tup.vals()))};
} }
return {}; return {};
} }
static inline Result force(any_tuple const& tup, pattern<T...> const&) static inline Result force(any_tuple& tup, pattern<T...> const&)
{ {
return {Result::from(tup.vals())}; return {Result::from(std::move(tup.vals()))};
} }
}; };
template<class Result, typename... T> template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::leading, Result, T...> struct tuple_cast_impl<wildcard_position::leading, Result, T...>
{ {
static inline option<Result> safe(any_tuple const& tup) static inline option<Result> safe(any_tuple& tup)
{ {
size_t o = tup.size() - (sizeof...(T) - 1); size_t o = tup.size() - (sizeof...(T) - 1);
if (matches<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)}; if (matches<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)};
return {}; return {};
} }
static inline option<Result> safe(any_tuple const& tup, pattern<T...> const& p) static inline option<Result> safe(any_tuple& tup, pattern<T...> const& p)
{ {
size_t o = tup.size() - (sizeof...(T) - 1); size_t o = tup.size() - (sizeof...(T) - 1);
if (matches(tup, p)) return {Result::offset_subtuple(tup.vals(), o)}; if (matches(tup, p)) return {Result::offset_subtuple(tup.vals(), o)};
return {}; return {};
} }
static inline option<Result> unsafe(any_tuple const& 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, T...>::vmatch(tup, p))
...@@ -190,7 +196,7 @@ struct tuple_cast_impl<wildcard_position::leading, Result, T...> ...@@ -190,7 +196,7 @@ struct tuple_cast_impl<wildcard_position::leading, Result, T...>
} }
return {}; return {};
} }
static inline Result force(any_tuple const& tup, pattern<T...> const&) static inline Result force(any_tuple& tup, pattern<T...> const&)
{ {
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);
......
...@@ -59,11 +59,14 @@ class tuple_vals : public abstract_tuple ...@@ -59,11 +59,14 @@ class tuple_vals : public abstract_tuple
typedef types_array<ElementTypes...> element_types; typedef types_array<ElementTypes...> element_types;
tuple_vals() : m_data() { } tuple_vals() : super(tuple_impl_info::statically_typed), m_data() { }
tuple_vals(tuple_vals const& other) : super(), m_data(other.m_data) { } tuple_vals(tuple_vals const&) = default;
tuple_vals(ElementTypes const&... args) : m_data(args...) { } tuple_vals(ElementTypes const&... args)
: super(tuple_impl_info::statically_typed), m_data(args...)
{
}
inline data_type& data() inline data_type& data()
{ {
...@@ -114,12 +117,7 @@ class tuple_vals : public abstract_tuple ...@@ -114,12 +117,7 @@ class tuple_vals : public abstract_tuple
return abstract_tuple::equals(other); return abstract_tuple::equals(other);
} }
void const* type_token() const std::type_info const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
std::type_info const* impl_type() const
{ {
return detail::static_type_list<ElementTypes...>::list; return detail::static_type_list<ElementTypes...>::list;
} }
......
...@@ -57,6 +57,8 @@ class tuple_view : public abstract_tuple ...@@ -57,6 +57,8 @@ class tuple_view : public abstract_tuple
static_assert(sizeof...(ElementTypes) > 0, static_assert(sizeof...(ElementTypes) > 0,
"tuple_vals is not allowed to be empty"); "tuple_vals is not allowed to be empty");
typedef abstract_tuple super;
public: public:
typedef tdata<ElementTypes*...> data_type; typedef tdata<ElementTypes*...> data_type;
...@@ -69,7 +71,10 @@ class tuple_view : public abstract_tuple ...@@ -69,7 +71,10 @@ class tuple_view : public abstract_tuple
/** /**
* @warning @p tuple_view does @b NOT takes ownership for given pointers * @warning @p tuple_view does @b NOT takes ownership for given pointers
*/ */
tuple_view(ElementTypes*... args) : m_data(args...) { } tuple_view(ElementTypes*... args)
: super(tuple_impl_info::statically_typed), m_data(args...)
{
}
inline data_type& data() inline data_type& data()
{ {
...@@ -112,12 +117,7 @@ class tuple_view : public abstract_tuple ...@@ -112,12 +117,7 @@ class tuple_view : public abstract_tuple
return m_types[pos]; return m_types[pos];
} }
void const* type_token() const std::type_info const* type_token() const
{
return detail::static_type_list<ElementTypes...>::list;
}
std::type_info const* impl_type() const
{ {
return detail::static_type_list<ElementTypes...>::list; return detail::static_type_list<ElementTypes...>::list;
} }
......
...@@ -38,23 +38,29 @@ namespace cppa { namespace detail { ...@@ -38,23 +38,29 @@ namespace cppa { namespace detail {
struct match_helper struct match_helper
{ {
match_helper(match_helper const&) = delete;
match_helper& operator=(match_helper const&) = delete;
any_tuple tup; any_tuple tup;
match_helper(any_tuple t) : tup(std::move(t)) { } match_helper(any_tuple&& t) : tup(std::move(t)) { }
match_helper(match_helper&&) = default;
template<class... Args> template<class... Args>
void operator()(partial_function&& pf, Args&&... args) void operator()(partial_function&& pf, Args&&... args)
{ {
partial_function tmp; partial_function tmp;
tmp.splice(std::move(pf), std::forward<Args>(args)...); tmp.splice(std::move(pf), std::forward<Args>(args)...);
tmp(tup); tmp(std::move(tup));
} }
}; };
template<typename Iterator> template<typename Iterator>
struct match_each_helper struct match_each_helper
{ {
match_each_helper(match_each_helper const&) = delete;
match_each_helper& operator=(match_each_helper const&) = delete;
Iterator i; Iterator i;
Iterator e; Iterator e;
match_each_helper(Iterator first, Iterator last) : i(first), e(last) { } match_each_helper(Iterator first, Iterator last) : i(first), e(last) { }
match_each_helper(match_each_helper&&) = default;
template<typename... Args> template<typename... Args>
void operator()(partial_function&& arg0, Args&&... args) void operator()(partial_function&& arg0, Args&&... args)
{ {
...@@ -70,11 +76,17 @@ struct match_each_helper ...@@ -70,11 +76,17 @@ struct match_each_helper
template<typename Iterator, typename Projection> template<typename Iterator, typename Projection>
struct pmatch_each_helper struct pmatch_each_helper
{ {
pmatch_each_helper(pmatch_each_helper const&) = delete;
pmatch_each_helper& operator=(pmatch_each_helper const&) = delete;
Iterator i; Iterator i;
Iterator e; Iterator e;
Projection p; Projection p;
pmatch_each_helper(pmatch_each_helper&&) = default;
template<typename PJ> template<typename PJ>
pmatch_each_helper(Iterator first, Iterator last, PJ&& proj) : i(first), e(last), p(std::forward<PJ>(proj)) { } pmatch_each_helper(Iterator first, Iterator last, PJ&& proj)
: i(first), e(last), p(std::forward<PJ>(proj))
{
}
template<typename... Args> template<typename... Args>
void operator()(partial_function&& arg0, Args&&... args) void operator()(partial_function&& arg0, Args&&... args)
{ {
...@@ -91,6 +103,11 @@ struct pmatch_each_helper ...@@ -91,6 +103,11 @@ struct pmatch_each_helper
namespace cppa { namespace cppa {
//inline detail::match_helper match(any_tuple t)
//{
// return std::move(t);
//}
/** /**
* @brief Match expression. * @brief Match expression.
*/ */
......
...@@ -65,11 +65,11 @@ class partial_function ...@@ -65,11 +65,11 @@ class partial_function
bool defined_at(any_tuple const& value); bool defined_at(any_tuple const& value);
void operator()(any_tuple const& value); void operator()(any_tuple value);
detail::invokable const* definition_at(any_tuple const& value); detail::invokable const* definition_at(any_tuple value);
detail::intermediate* get_intermediate(any_tuple const& value); detail::intermediate* get_intermediate(any_tuple value);
template<class... Args> template<class... Args>
partial_function& splice(partial_function&& arg0, Args&&... args) partial_function& splice(partial_function&& arg0, Args&&... args)
......
...@@ -43,7 +43,7 @@ std::string to_string_impl(void const* what, uniform_type_info const* utype); ...@@ -43,7 +43,7 @@ std::string to_string_impl(void const* what, uniform_type_info const* utype);
} // namespace detail } // namespace detail
/** /**
* @brief Serializes a value to a string. * @brief Serializes a value to a string representation.
* @param what A value of an announced type. * @param what A value of an announced type.
* @returns A string representation of @p what. * @returns A string representation of @p what.
*/ */
......
...@@ -121,19 +121,19 @@ class tuple ...@@ -121,19 +121,19 @@ class tuple
inline static tuple from(cow_ptr_type ptr) inline static tuple from(cow_ptr_type ptr)
{ {
return {priv_ctor(), std::move(ptr)}; return {priv_ctor{}, std::move(ptr)};
} }
inline static tuple from(cow_ptr_type ptr, inline static tuple from(cow_ptr_type ptr,
util::fixed_vector<size_t, num_elements> const& mv) util::fixed_vector<size_t, num_elements> const& mv)
{ {
return {priv_ctor(), decorated_type::create(std::move(ptr), mv)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), mv)};
} }
inline static tuple offset_subtuple(cow_ptr_type ptr, size_t offset) inline static tuple offset_subtuple(cow_ptr_type ptr, size_t offset)
{ {
CPPA_REQUIRE(offset > 0); CPPA_REQUIRE(offset > 0);
return {priv_ctor(), decorated_type::create(std::move(ptr), offset)}; return {priv_ctor{}, decorated_type::create(std::move(ptr), offset)};
} }
/** /**
......
...@@ -42,10 +42,11 @@ ...@@ -42,10 +42,11 @@
namespace cppa { namespace cppa {
/** /**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}. * @brief Tries to cast @p tup to {@link tuple tuple<T...>}; moves content
* of @p tup on success.
*/ */
template<typename... T> template<typename... T>
auto tuple_cast(any_tuple const& tup, pattern<T...> const& p) auto moving_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> option< -> option<
typename tuple_from_type_list< typename tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
...@@ -59,28 +60,70 @@ auto tuple_cast(any_tuple const& tup, pattern<T...> const& p) ...@@ -59,28 +60,70 @@ auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
} }
/** /**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}. * @brief Tries to cast @p tup to {@link tuple tuple<T...>}; moves content
* of @p tup on success.
*/ */
template<typename... T> template<typename... T>
auto tuple_cast(any_tuple const& tup) auto moving_tuple_cast(any_tuple& tup)
-> option< -> option<
typename tuple_from_type_list< typename tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>, typename util::tl_filter_not<util::type_list<T...>,
is_anything>::type is_anything>::type
>::type> >::type>
{ {
typedef decltype(tuple_cast<T...>(tup)) result_type; typedef decltype(moving_tuple_cast<T...>(tup)) result_type;
typedef typename result_type::value_type tuple_type; typedef typename result_type::value_type tuple_type;
static constexpr auto impl = static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>(); get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup); return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup);
} }
template<typename... T>
auto moving_tuple_cast(any_tuple& tup, util::type_list<T...> const&)
-> decltype(moving_tuple_cast<T...>(tup))
{
return moving_tuple_cast<T...>(tup);
}
/**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}.
*/
template<typename... T>
auto tuple_cast(any_tuple tup, pattern<T...> const& p)
-> option<
typename tuple_from_type_list<
typename pattern<T...>::filtered_types
>::type>
{
return moving_tuple_cast(tup, p);
}
/**
* @brief Tries to cast @p tup to {@link tuple tuple<T...>}.
*/
template<typename... T>
auto tuple_cast(any_tuple tup)
-> option<
typename tuple_from_type_list<
typename util::tl_filter_not<util::type_list<T...>,
is_anything>::type
>::type>
{
return moving_tuple_cast<T...>(tup);
}
template<typename... T>
auto tuple_cast(any_tuple tup, util::type_list<T...> const&)
-> decltype(tuple_cast<T...>(tup))
{
return moving_tuple_cast<T...>(tup);
}
/////////////////////////// for in-library use only! /////////////////////////// /////////////////////////// for in-library use only! ///////////////////////////
// cast using a pattern; does not perform type checking // (moving) cast using a pattern; does not perform type checking
template<typename... T> template<typename... T>
auto unsafe_tuple_cast(any_tuple const& tup, pattern<T...> const& p) auto unsafe_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> option< -> option<
typename tuple_from_type_list< typename tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
...@@ -93,9 +136,16 @@ auto unsafe_tuple_cast(any_tuple const& tup, pattern<T...> const& p) ...@@ -93,9 +136,16 @@ auto unsafe_tuple_cast(any_tuple const& tup, pattern<T...> const& p)
return detail::tuple_cast_impl<impl, tuple_type, T...>::unsafe(tup, p); return detail::tuple_cast_impl<impl, tuple_type, T...>::unsafe(tup, p);
} }
template<typename... T>
auto unsafe_tuple_cast(any_tuple& tup, util::type_list<T...> const&)
-> decltype(tuple_cast<T...>(tup))
{
return tuple_cast<T...>(tup);
}
// cast using a pattern; does neither perform type checking nor checks values // cast using a pattern; does neither perform type checking nor checks values
template<typename... T> template<typename... T>
auto forced_tuple_cast(any_tuple const& tup, pattern<T...> const& p) auto forced_tuple_cast(any_tuple& tup, pattern<T...> const& p)
-> typename tuple_from_type_list< -> typename tuple_from_type_list<
typename pattern<T...>::filtered_types typename pattern<T...>::filtered_types
>::type >::type
......
...@@ -118,7 +118,7 @@ int main(int, char**) ...@@ -118,7 +118,7 @@ int main(int, char**)
int i = 0; int i = 0;
receive_while([&]() { return ++i <= 2; }) receive_while([&]() { return ++i <= 2; })
( (
on<bar>() >> [](const bar& val) on<bar>() >> [](bar const& val)
{ {
cout << "bar(foo(" cout << "bar(foo("
<< val.f.a() << "," << val.f.a() << ","
...@@ -126,12 +126,11 @@ int main(int, char**) ...@@ -126,12 +126,11 @@ int main(int, char**)
<< val.i << ")" << val.i << ")"
<< endl; << endl;
}, },
on<baz>() >> []() on<baz>() >> [](baz const& val)
{ {
// prints: @<> ( { baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) ) } ) // prints: baz ( foo ( 1, 2 ), bar ( foo ( 3, 4 ), 5 ) )
cout << to_string(self->last_dequeued()) << endl; cout << to_string(val) << endl;
} }
); );
return 0; return 0;
} }
......
...@@ -39,6 +39,15 @@ bool abstract_tuple::equals(const abstract_tuple &other) const ...@@ -39,6 +39,15 @@ bool abstract_tuple::equals(const abstract_tuple &other) const
&& std::equal(begin(), end(), other.begin(), detail::full_eq_v3)); && std::equal(begin(), end(), other.begin(), detail::full_eq_v3));
} }
abstract_tuple::abstract_tuple(abstract_tuple const&) : ref_counted() { } abstract_tuple::abstract_tuple(abstract_tuple const& other)
: ref_counted()
, m_impl_type(other.m_impl_type)
{
}
std::type_info const* abstract_tuple::type_token() const
{
return &typeid(void);
}
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -34,51 +34,6 @@ ...@@ -34,51 +34,6 @@
namespace { namespace {
/*
struct offset_decorator : cppa::detail::abstract_tuple
{
typedef cppa::cow_ptr<cppa::detail::abstract_tuple> ptr_type;
offset_decorator(ptr_type const& decorated, size_t offset)
: m_offset(offset)
, m_decorated(decorated)
{
}
void* mutable_at(size_t pos)
{
return m_decorated->mutable_at(pos + m_offset);
}
size_t size() const
{
return m_decorated->size() - m_offset;
}
abstract_tuple* copy() const
{
return new offset_decorator(m_decorated, m_offset);
}
const void* at(size_t pos) const
{
return m_decorated->at(pos + m_offset);
}
const cppa::uniform_type_info* type_at(size_t pos) const
{
return m_decorated->type_at(pos + m_offset);
}
private:
size_t m_offset;
ptr_type m_decorated;
};
*/
inline cppa::detail::empty_tuple* s_empty_tuple() inline cppa::detail::empty_tuple* s_empty_tuple()
{ {
return cppa::detail::singleton_manager::get_empty_tuple(); return cppa::detail::singleton_manager::get_empty_tuple();
...@@ -131,11 +86,6 @@ const uniform_type_info* any_tuple::type_at(size_t p) const ...@@ -131,11 +86,6 @@ const uniform_type_info* any_tuple::type_at(size_t p) const
return m_vals->type_at(p); return m_vals->type_at(p);
} }
const cow_ptr<detail::abstract_tuple>& any_tuple::vals() const
{
return m_vals;
}
bool any_tuple::equals(any_tuple const& other) const bool any_tuple::equals(any_tuple const& other) const
{ {
return m_vals->equals(*other.vals()); return m_vals->equals(*other.vals());
......
...@@ -33,6 +33,10 @@ ...@@ -33,6 +33,10 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
empty_tuple::empty_tuple() : abstract_tuple(tuple_impl_info::statically_typed)
{
}
size_t empty_tuple::size() const size_t empty_tuple::size() const
{ {
return 0; return 0;
...@@ -63,14 +67,9 @@ bool empty_tuple::equals(const abstract_tuple& other) const ...@@ -63,14 +67,9 @@ bool empty_tuple::equals(const abstract_tuple& other) const
return other.size() == 0; return other.size() == 0;
} }
void const* empty_tuple::type_token() const std::type_info const* empty_tuple::type_token() const
{
return &typeid(empty_tuple);
}
std::type_info const* empty_tuple::impl_type() const
{ {
return &typeid(empty_tuple); return &typeid(util::type_list<>);
} }
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -36,16 +36,16 @@ invokable::~invokable() ...@@ -36,16 +36,16 @@ invokable::~invokable()
{ {
} }
bool invokable::invoke(any_tuple const&) const { return false; } bool invokable::invoke(any_tuple&) const { return false; }
bool invokable::unsafe_invoke(any_tuple const&) const { return false; } bool invokable::unsafe_invoke(any_tuple&) const { return false; }
bool invokable::types_match(any_tuple const&) const { return false; } bool invokable::types_match(any_tuple const&) const { return false; }
bool invokable::could_invoke(any_tuple const&) const { return false; } bool invokable::could_invoke(any_tuple const&) const { return false; }
intermediate* invokable::get_intermediate(any_tuple const&) { return 0; } intermediate* invokable::get_intermediate(any_tuple&) { return 0; }
intermediate* invokable::get_unsafe_intermediate(any_tuple const&) { return 0; } intermediate* invokable::get_unsafe_intermediate(any_tuple&) { return 0; }
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
namespace cppa { namespace detail { namespace cppa { namespace detail {
object_array::object_array() : super(tuple_impl_info::dynamically_typed)
{
}
void object_array::push_back(object const& what) void object_array::push_back(object const& what)
{ {
m_elements.push_back(what); m_elements.push_back(what);
...@@ -67,14 +71,4 @@ uniform_type_info const* object_array::type_at(size_t pos) const ...@@ -67,14 +71,4 @@ uniform_type_info const* object_array::type_at(size_t pos) const
return m_elements[pos].type(); return m_elements[pos].type();
} }
void const* object_array::type_token() const
{
return &typeid(object_array);
}
std::type_info const* object_array::impl_type() const
{
return &typeid(object_array);
}
} } // namespace cppa::detail } } // namespace cppa::detail
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
\******************************************************************************/ \******************************************************************************/
#include "cppa/to_string.hpp"
#include "cppa/config.hpp" #include "cppa/config.hpp"
#include "cppa/behavior.hpp" #include "cppa/behavior.hpp"
#include "cppa/partial_function.hpp" #include "cppa/partial_function.hpp"
...@@ -66,11 +68,23 @@ auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry& ...@@ -66,11 +68,23 @@ auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry&
// if we didn't found a cache entry ... // if we didn't found a cache entry ...
if (i == end || i->first != m_dummy.first) if (i == end || i->first != m_dummy.first)
{ {
// ... create one (store all invokables with matching types) // ... create one
cache_entry tmp; cache_entry tmp;
for (auto f = m_funs.begin(); f != m_funs.end(); ++f) if (value.impl_type() == detail::tuple_impl_info::statically_typed)
{
// use static type information for optimal caching
for (auto f = m_funs.begin(); f != m_funs.end(); ++f)
{
if (f->types_match(value)) tmp.push_back(f.ptr());
}
}
else
{ {
if (f->types_match(value)) tmp.push_back(f.ptr()); // "dummy" cache entry with all functions (dynamically typed tuple)
for (auto f = m_funs.begin(); f != m_funs.end(); ++f)
{
tmp.push_back(f.ptr());
}
} }
// m_cache is always sorted, // m_cache is always sorted,
// due to emplace(upper_bound, ...) insertions // due to emplace(upper_bound, ...) insertions
...@@ -79,20 +93,31 @@ auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry& ...@@ -79,20 +93,31 @@ auto partial_function::get_cache_entry(any_tuple const& value) -> cache_entry&
return i->second; return i->second;
} }
void partial_function::operator()(any_tuple const& value) void partial_function::operator()(any_tuple value)
{ {
using detail::invokable;
auto& v = get_cache_entry(value); auto& v = get_cache_entry(value);
(void) std::any_of( if (value.impl_type() == detail::tuple_impl_info::statically_typed)
v.begin(), v.end(), {
[&](detail::invokable* i) { return i->unsafe_invoke(value); }); std::any_of(v.begin(), v.end(),
[&](invokable* i) { return i->unsafe_invoke(value); });
}
else
{
std::any_of(v.begin(), v.end(),
[&](invokable* i) { return i->invoke(value); });
}
} }
detail::invokable const* partial_function::definition_at(any_tuple const& value) detail::invokable const* partial_function::definition_at(any_tuple value)
{ {
using detail::invokable;
auto& v = get_cache_entry(value); auto& v = get_cache_entry(value);
auto i = std::find_if( auto i = (value.impl_type() == detail::tuple_impl_info::statically_typed)
v.begin(), v.end(), ? std::find_if(v.begin(), v.end(),
[&](detail::invokable* i) { return i->could_invoke(value); }); [&](invokable* i) { return i->could_invoke(value);})
: std::find_if(v.begin(), v.end(),
[&](invokable* i) { return i->invoke(value); });
return (i != v.end()) ? *i : nullptr; return (i != v.end()) ? *i : nullptr;
} }
...@@ -101,15 +126,20 @@ bool partial_function::defined_at(any_tuple const& value) ...@@ -101,15 +126,20 @@ bool partial_function::defined_at(any_tuple const& value)
return definition_at(value) != nullptr; return definition_at(value) != nullptr;
} }
detail::intermediate* partial_function::get_intermediate(any_tuple const& value) detail::intermediate* partial_function::get_intermediate(any_tuple value)
{ {
detail::intermediate* result = nullptr; detail::intermediate* result = nullptr;
for (auto& i : get_cache_entry(value)) if (value.impl_type() == detail::tuple_impl_info::statically_typed)
{ {
if ((result = i->get_unsafe_intermediate(value)) != nullptr) for (auto& i : get_cache_entry(value))
{ if ((result = i->get_unsafe_intermediate(value)) != nullptr)
return result; return result;
} }
else
{
for (auto& i : get_cache_entry(value))
if ((result = i->get_intermediate(value)) != nullptr)
return result;
} }
return nullptr; return nullptr;
} }
......
...@@ -65,6 +65,15 @@ using std::endl; ...@@ -65,6 +65,15 @@ using std::endl;
using namespace cppa; using namespace cppa;
std::vector<std::string> split(std::string const& str, char delim)
{
std::vector<std::string> result;
std::stringstream strs{str};
std::string tmp;
while (std::getline(strs, tmp, delim)) result.push_back(tmp);
return result;
}
void print_node_id() void print_node_id()
{ {
auto pinfo = cppa::process_information::get(); auto pinfo = cppa::process_information::get();
...@@ -78,15 +87,6 @@ void print_node_id() ...@@ -78,15 +87,6 @@ void print_node_id()
<< endl; << endl;
} }
std::vector<std::string> split(std::string const& str, char delim)
{
std::vector<std::string> result;
std::stringstream strs{str};
std::string tmp;
while (std::getline(strs, tmp, delim)) result.push_back(tmp);
return result;
}
std::vector<string_pair> get_kv_pairs(int argc, char** argv, int begin = 1) std::vector<string_pair> get_kv_pairs(int argc, char** argv, int begin = 1)
{ {
std::vector<string_pair> result; std::vector<string_pair> result;
...@@ -121,16 +121,6 @@ void usage(char const* argv0) ...@@ -121,16 +121,6 @@ void usage(char const* argv0)
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
/* /*
std::string abc = "abc";
cout << "is_iterable<string> = " << cppa::util::is_iterable<std::string>::value << endl;
match(abc)
(
on("abc") >> []()
{
cout << "ABC" << endl;
}
);
match_each(argv + 1, argv + argc) match_each(argv + 1, argv + argc)
( (
on_arg_match >> [](std::string const& str) on_arg_match >> [](std::string const& str)
...@@ -145,11 +135,15 @@ int main(int argc, char** argv) ...@@ -145,11 +135,15 @@ int main(int argc, char** argv)
{ {
cout << "key = \"" << key << "\", value = \"" << value << "\"" cout << "key = \"" << key << "\", value = \"" << value << "\""
<< endl; << endl;
},
others() >> [](any_tuple const& oops)
{
cout << "not a key value pair: " << to_string(oops) << endl;
} }
); );
return 0; return 0;
*/ //*/
auto args = get_kv_pairs(argc, argv); auto args = get_kv_pairs(argc, argv);
match_each(args) match_each(args)
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include <cstddef> #include <cstddef>
#include <sstream>
#include <iostream> #include <iostream>
#include <type_traits> #include <type_traits>
...@@ -110,6 +111,8 @@ size_t test__intrusive_containers(); ...@@ -110,6 +111,8 @@ size_t test__intrusive_containers();
void test__queue_performance(); void test__queue_performance();
std::vector<std::string> split(std::string const& str, char delim);
using std::cout; using std::cout;
using std::endl; using std::endl;
using std::cerr; using std::cerr;
......
#include <functional>
#include "test.hpp" #include "test.hpp"
#include "cppa/on.hpp"
#include "cppa/match.hpp" #include "cppa/match.hpp"
#include "cppa/announce.hpp"
#include "cppa/to_string.hpp"
using namespace cppa;
using std::vector;
using std::string;
size_t test__match() size_t test__match()
{ {
CPPA_TEST(test__match); CPPA_TEST(test__match);
bool invoked = false;
match("abc")
(
on("abc") >> [&]()
{
invoked = true;
}
);
if (!invoked) { CPPA_ERROR("match(\"abc\") failed"); }
invoked = false;
vector<string> vec{"a", "b", "c"};
match(vec)
(
on("a", "b", arg_match) >> [&](string& str)
{
invoked = true;
str = "C";
}
);
if (!invoked) { CPPA_ERROR("match({\"a\", \"b\", \"c\"}) failed"); }
CPPA_CHECK_EQUAL("C", vec.back());
invoked = false;
match_each(vec)
(
on("a") >> [&](string& str)
{
invoked = true;
str = "A";
}
);
if (!invoked) { CPPA_ERROR("match_each({\"a\", \"b\", \"C\"}) failed"); }
CPPA_CHECK_EQUAL("A", vec.front());
invoked = false;
match(vec)
(
others() >> [&](any_tuple& tup)
{
if (detail::matches<string, string, string>(tup))
{
tup.get_as_mutable<string>(1) = "B";
}
else
{
CPPA_ERROR("matches<string, string, string>(tup) == false");
}
invoked = true;
}
);
if (!invoked) { CPPA_ERROR("match({\"a\", \"b\", \"c\"}) failed"); }
CPPA_CHECK_EQUAL(vec[1], "B");
invoked = false;
vector<string> vec2{"a=0", "b=1", "c=2"};
auto c2 = split(vec2.back(), '=');
match(c2)
(
on("c", "2") >> [&]() { invoked = true; }
);
CPPA_CHECK_EQUAL(true, invoked);
invoked = false;
int pmatches = 0;
using std::placeholders::_1;
pmatch_each(vec2.begin(), vec2.end(), std::bind(split, _1, '='))
(
on("a", arg_match) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("0", value);
CPPA_CHECK_EQUAL(0, pmatches);
++pmatches;
},
on("b", arg_match) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("1", value);
CPPA_CHECK_EQUAL(1, pmatches);
++pmatches;
},
on("c", arg_match) >> [&](string const& value)
{
CPPA_CHECK_EQUAL("2", value);
CPPA_CHECK_EQUAL(2, pmatches);
++pmatches;
},
others() >> [](any_tuple const& value)
{
cout << to_string(value) << endl;
}
);
CPPA_CHECK_EQUAL(3, pmatches);
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
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