Commit b27b52d6 authored by neverlord's avatar neverlord

tuple_cast

parent 408022cf
...@@ -36,9 +36,11 @@ ...@@ -36,9 +36,11 @@
#include <cstdint> #include <cstdint>
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/tuple_cast.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
#include "cppa/util/apply_tuple.hpp" #include "cppa/util/apply_tuple.hpp"
#include "cppa/util/fixed_vector.hpp" #include "cppa/util/fixed_vector.hpp"
#include "cppa/util/callable_trait.hpp"
#include "cppa/detail/matches.hpp" #include "cppa/detail/matches.hpp"
#include "cppa/detail/intermediate.hpp" #include "cppa/detail/intermediate.hpp"
...@@ -113,57 +115,34 @@ class invokable : public invokable_base ...@@ -113,57 +115,34 @@ class invokable : public invokable_base
}; };
template<class TupleView, class Pattern, class TargetFun> template<size_t NumArgs, typename Fun, class Tuple, class Pattern>
class invokable_impl : public invokable class invokable_impl : public invokable
{ {
typedef typename Pattern::mapping_vector vector_type;
struct iimpl : intermediate struct iimpl : intermediate
{ {
TargetFun m_target; Fun m_fun;
TupleView m_args; Tuple m_args;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
template<typename F> void invoke() { util::apply_tuple(m_fun, m_args); }
iimpl(F&& fun) : m_target(std::forward<F>(fun)) }
{ m_iimpl;
}
void invoke() // override
{
util::apply_tuple(m_target, m_args);
}
};
std::unique_ptr<Pattern> m_pattern; std::unique_ptr<Pattern> m_pattern;
iimpl m_iimpl;
public: public:
template<typename F> template<typename F>
invokable_impl(std::unique_ptr<Pattern>&& pptr, F&& fun) invokable_impl(F&& fun, std::unique_ptr<Pattern>&& pptr)
: m_pattern(std::move(pptr)), m_iimpl(std::forward<F>(fun)) : m_iimpl(std::forward<F>(fun)), m_pattern(std::move(pptr))
{ {
} }
bool invoke(any_tuple const& data) const bool invoke(any_tuple const& data) const
{ {
vector_type mv; auto tuple_option = tuple_cast(data, *m_pattern);
if (detail::matches(pm_decorated(data.begin(), &mv), m_pattern->begin())) if (tuple_option.valid())
//if ((*m_pattern)(data, &mv))
{ {
if (mv.size() == data.size()) util::apply_tuple(m_iimpl.m_fun, *tuple_option);
{
// "perfect" match; no mapping needed at all
TupleView tv = TupleView::from(data.vals());
util::apply_tuple(m_iimpl.m_target, tv);
}
else
{
// mapping needed
TupleView tv(data.vals(), mv);
util::apply_tuple(m_iimpl.m_target, tv);
}
return true; return true;
} }
return false; return false;
...@@ -171,19 +150,10 @@ class invokable_impl : public invokable ...@@ -171,19 +150,10 @@ class invokable_impl : public invokable
intermediate* get_intermediate(any_tuple const& data) intermediate* get_intermediate(any_tuple const& data)
{ {
vector_type mv; auto tuple_option = tuple_cast(data, *m_pattern);
//if ((*m_pattern)(data, &mv)) if (tuple_option.valid())
if (detail::matches(pm_decorated(data.begin(), &mv), m_pattern->begin()))
{ {
if (mv.size() == data.size()) m_iimpl.m_args = std::move(*tuple_option);
{
// perfect match
m_iimpl.m_args = TupleView::from(data.vals());
}
else
{
m_iimpl.m_args = TupleView(data.vals(), mv);
}
return &m_iimpl; return &m_iimpl;
} }
return nullptr; return nullptr;
...@@ -191,42 +161,32 @@ class invokable_impl : public invokable ...@@ -191,42 +161,32 @@ class invokable_impl : public invokable
}; };
template<template<class...> class TupleClass, class Pattern, class TargetFun> template<typename Fun, class Tuple, class Pattern>
class invokable_impl<TupleClass<>, Pattern, TargetFun> : public invokable class invokable_impl<0, Fun, Tuple, Pattern> : public invokable
{ {
struct iimpl : intermediate struct iimpl : intermediate
{ {
TargetFun m_target; Fun m_fun;
template<typename F> iimpl(F&& fun) : m_fun(std::forward<F>(fun)) { }
template<typename F> void invoke() { m_fun(); }
iimpl(F&& fun) : m_target(fun) }
{ m_iimpl;
}
void invoke()
{
m_target();
}
};
std::unique_ptr<Pattern> m_pattern; std::unique_ptr<Pattern> m_pattern;
iimpl m_iimpl;
public: public:
template<typename F> template<typename F>
invokable_impl(std::unique_ptr<Pattern>&& pptr, F&& fun) invokable_impl(F&& fun, std::unique_ptr<Pattern>&& pptr)
: m_pattern(std::move(pptr)), m_iimpl(std::forward<F>(fun)) : m_iimpl(std::forward<F>(fun)), m_pattern(std::move(pptr))
{ {
} }
bool invoke(any_tuple const& data) const bool invoke(any_tuple const& data) const
{ {
if (detail::matches(data.begin(), m_pattern->begin())) if (detail::matches(data.begin(), m_pattern->begin()))
//if ((*m_pattern)(data, nullptr))
{ {
m_iimpl.m_target(); m_iimpl.m_fun();
return true; return true;
} }
return false; return false;
...@@ -236,11 +196,29 @@ class invokable_impl<TupleClass<>, Pattern, TargetFun> : public invokable ...@@ -236,11 +196,29 @@ class invokable_impl<TupleClass<>, Pattern, TargetFun> : public invokable
{ {
return detail::matches(data.begin(), m_pattern->begin()) ? &m_iimpl return detail::matches(data.begin(), m_pattern->begin()) ? &m_iimpl
: nullptr; : nullptr;
//return ((*m_pattern)(data, nullptr)) ? &m_iimpl : nullptr;
} }
}; };
template<typename Fun, class Pattern>
struct select_invokable_impl
{
typedef typename util::get_arg_types<Fun>::types arg_types;
typedef typename Pattern::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
typedef invokable_impl<arg_types::size, Fun, tuple_type, Pattern> type;
};
template<typename Fun, class Pattern>
std::unique_ptr<invokable> get_invokable_impl(Fun&& fun,
std::unique_ptr<Pattern>&& pptr)
{
typedef typename select_invokable_impl<Fun, Pattern>::type result;
return std::unique_ptr<invokable>(new result(std::forward<Fun>(fun),
std::move(pptr)));
}
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // INVOKABLE_HPP #endif // INVOKABLE_HPP
...@@ -116,6 +116,15 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>, ...@@ -116,6 +116,15 @@ struct types_array : types_array_impl<util::tl_forall<util::type_list<T...>,
{ {
}; };
template<typename... T>
struct static_types_array
{
static types_array<T...> arr;
};
template<typename... T>
types_array<T...> static_types_array<T...>::arr;
} } // namespace cppa::detail } } // namespace cppa::detail
#endif // TYPES_ARRAY_HPP #endif // TYPES_ARRAY_HPP
...@@ -38,7 +38,6 @@ ...@@ -38,7 +38,6 @@
#include "cppa/pattern.hpp" #include "cppa/pattern.hpp"
#include "cppa/anything.hpp" #include "cppa/anything.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/tuple_view.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/util/duration.hpp" #include "cppa/util/duration.hpp"
...@@ -103,13 +102,10 @@ class invoke_rule_builder ...@@ -103,13 +102,10 @@ class invoke_rule_builder
std::unique_ptr<pattern_type> m_ptr; std::unique_ptr<pattern_type> m_ptr;
typedef typename tuple_view_type_from_type_list<typename pattern_type::filtered_types>::type tuple_view_type;
template<typename F> template<typename F>
invoke_rules cr_rules(F&& f, std::integral_constant<bool, true>) invoke_rules cr_rules(F&& f, std::integral_constant<bool, true>)
{ {
typedef invokable_impl<tuple_view_type, pattern_type, F> impl; return get_invokable_impl(std::forward<F>(f), std::move(m_ptr));
return invokable_ptr(new impl(std::move(m_ptr),std::forward<F>(f)));
} }
template<typename F> template<typename F>
...@@ -122,13 +118,8 @@ class invoke_rule_builder ...@@ -122,13 +118,8 @@ class invoke_rule_builder
typedef typename tl_apply<raw_types,rm_ref>::type new_types; typedef typename tl_apply<raw_types,rm_ref>::type new_types;
typedef typename tl_concat<converted_types,new_types>::type types; typedef typename tl_concat<converted_types,new_types>::type types;
typedef typename pattern_from_type_list<types>::type epattern; typedef typename pattern_from_type_list<types>::type epattern;
//typedef typename epattern::tuple_view_type tuple_view_type;
typedef typename tuple_view_type_from_type_list<typename epattern::filtered_types>::type tuple_view_type;
typedef invokable_impl<tuple_view_type, epattern, F> impl;
std::unique_ptr<epattern> pptr(extend_pattern<epattern>(m_ptr.get())); std::unique_ptr<epattern> pptr(extend_pattern<epattern>(m_ptr.get()));
return invokable_ptr(new impl(std::move(pptr), std::forward<F>(f))); return get_invokable_impl(std::forward<F>(f), std::move(pptr));
} }
public: public:
...@@ -167,13 +158,8 @@ class on_the_fly_invoke_rule_builder ...@@ -167,13 +158,8 @@ class on_the_fly_invoke_rule_builder
static_assert(raw_types::size > 0, "functor has no arguments"); static_assert(raw_types::size > 0, "functor has no arguments");
typedef typename tl_apply<raw_types,rm_ref>::type types; typedef typename tl_apply<raw_types,rm_ref>::type types;
typedef typename pattern_from_type_list<types>::type pattern_type; typedef typename pattern_from_type_list<types>::type pattern_type;
//typedef typename pattern_type::tuple_view_type tuple_view_type;
typedef typename tuple_view_type_from_type_list<typename pattern_type::filtered_types>::type tuple_view_type;
typedef invokable_impl<tuple_view_type, pattern_type, F> impl;
std::unique_ptr<pattern_type> pptr(new pattern_type); std::unique_ptr<pattern_type> pptr(new pattern_type);
return invokable_ptr(new impl(std::move(pptr), std::forward<F>(f))); return get_invokable_impl(std::forward<F>(f), std::move(pptr));
} }
}; };
......
...@@ -35,9 +35,12 @@ ...@@ -35,9 +35,12 @@
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/util/option.hpp" #include "cppa/util/option.hpp"
#include "cppa/detail/matches.hpp" #include "cppa/detail/matches.hpp"
#include "cppa/detail/types_array.hpp"
#include "cppa/detail/decorated_tuple.hpp"
namespace cppa { namespace cppa {
// cast using a pattern
template<typename... P> template<typename... P>
auto tuple_cast(any_tuple const& tup, pattern<P...> const& p) auto tuple_cast(any_tuple const& tup, pattern<P...> const& p)
-> util::option<typename tuple_from_type_list<typename pattern<P...>::filtered_types>::type> -> util::option<typename tuple_from_type_list<typename pattern<P...>::filtered_types>::type>
...@@ -61,6 +64,23 @@ auto tuple_cast(any_tuple const& tup, pattern<P...> const& p) ...@@ -61,6 +64,23 @@ auto tuple_cast(any_tuple const& tup, pattern<P...> const& p)
return std::move(result); return std::move(result);
} }
// cast using types
template<typename... T>
util::option< tuple<T...> > tuple_cast(any_tuple const& tup)
{
util::option< tuple<T...> > result;
auto& tarr = detail::static_types_array<T...>::arr;
if (tup.size() == sizeof...(T))
{
for (size_t i = 0; i < sizeof...(T); ++i)
{
if (tarr[i] != tup.type_at(i)) return std::move(result);
}
result = tuple<T...>::from(tup.vals());
}
return std::move(result);;
} }
} // namespace cppa
#endif // TUPLE_CAST_HPP #endif // TUPLE_CAST_HPP
...@@ -115,6 +115,10 @@ class option ...@@ -115,6 +115,10 @@ class option
inline bool valid() const { return m_valid; } inline bool valid() const { return m_valid; }
inline explicit operator bool() const { return m_valid; }
inline bool operator!() const { return !m_valid; }
inline What& operator*() { return m_value; } inline What& operator*() { return m_value; }
inline What const& operator*() const { return m_value; } inline What const& operator*() const { return m_value; }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/get_view.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
...@@ -124,10 +124,15 @@ size_t test__serialization() ...@@ -124,10 +124,15 @@ size_t test__serialization()
any_tuple atuple1(oarr); any_tuple atuple1(oarr);
try try
{ {
auto tv1 = get_view<std::uint32_t, std::string>(atuple1); auto opt = tuple_cast<std::uint32_t, std::string>(atuple1);
CPPA_CHECK_EQUAL(tv1.size(), 2); CPPA_CHECK(opt.valid());
CPPA_CHECK_EQUAL(get<0>(tv1), 42); if (opt)
CPPA_CHECK_EQUAL(get<1>(tv1), "foo"); {
auto& tup = *opt;
CPPA_CHECK_EQUAL(tup.size(), 2);
CPPA_CHECK_EQUAL(get<0>(tup), 42);
CPPA_CHECK_EQUAL(get<1>(tup), "foo");
}
} }
catch (std::exception& e) catch (std::exception& e)
{ {
...@@ -154,10 +159,15 @@ size_t test__serialization() ...@@ -154,10 +159,15 @@ size_t test__serialization()
uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd); uniform_typeid<any_tuple>()->deserialize(&atuple2, &bd);
try try
{ {
auto tview = get_view<std::uint32_t, std::string>(atuple2); auto opt = tuple_cast<std::uint32_t, std::string>(atuple2);
CPPA_CHECK_EQUAL(tview.size(), 2); CPPA_CHECK(opt.valid());
CPPA_CHECK_EQUAL(get<0>(tview), 42); if (opt.valid())
CPPA_CHECK_EQUAL(get<1>(tview), "foo"); {
auto& tup = *opt;
CPPA_CHECK_EQUAL(tup.size(), 2);
CPPA_CHECK_EQUAL(get<0>(tup), 42);
CPPA_CHECK_EQUAL(get<1>(tup), "foo");
}
} }
catch (std::exception& e) catch (std::exception& e)
{ {
...@@ -184,14 +194,20 @@ size_t test__serialization() ...@@ -184,14 +194,20 @@ size_t test__serialization()
{ {
auto& content1 = get<any_tuple>(obj1); auto& content1 = get<any_tuple>(obj1);
auto& content2 = get<any_tuple>(obj2); auto& content2 = get<any_tuple>(obj2);
auto cview1 = get_view<decltype(42), std::string>(content1); auto opt1 = tuple_cast<decltype(42), std::string>(content1);
auto cview2 = get_view<decltype(42), std::string>(content2); auto opt2 = tuple_cast<decltype(42), std::string>(content2);
CPPA_CHECK_EQUAL(cview1.size(), 2); CPPA_CHECK(opt1.valid() && opt2.valid());
CPPA_CHECK_EQUAL(cview2.size(), 2); if (opt1.valid() && opt2.valid())
CPPA_CHECK_EQUAL(get<0>(cview1), 42); {
CPPA_CHECK_EQUAL(get<0>(cview2), 42); auto& tup1 = *opt1;
CPPA_CHECK_EQUAL(get<1>(cview1), "Hello \"World\"!"); auto& tup2 = *opt2;
CPPA_CHECK_EQUAL(get<1>(cview2), "Hello \"World\"!"); CPPA_CHECK_EQUAL(tup1.size(), 2);
CPPA_CHECK_EQUAL(tup2.size(), 2);
CPPA_CHECK_EQUAL(get<0>(tup1), 42);
CPPA_CHECK_EQUAL(get<0>(tup2), 42);
CPPA_CHECK_EQUAL(get<1>(tup1), "Hello \"World\"!");
CPPA_CHECK_EQUAL(get<1>(tup2), "Hello \"World\"!");
}
} }
else else
{ {
......
...@@ -11,10 +11,9 @@ ...@@ -11,10 +11,9 @@
#include "cppa/on.hpp" #include "cppa/on.hpp"
#include "cppa/util.hpp" #include "cppa/util.hpp"
#include "cppa/tuple.hpp" #include "cppa/tuple.hpp"
#include "cppa/get_view.hpp"
#include "cppa/any_tuple.hpp" #include "cppa/any_tuple.hpp"
#include "cppa/to_string.hpp" #include "cppa/to_string.hpp"
#include "cppa/tuple_view.hpp" #include "cppa/tuple_cast.hpp"
#include "cppa/invoke_rules.hpp" #include "cppa/invoke_rules.hpp"
#include "cppa/intrusive_ptr.hpp" #include "cppa/intrusive_ptr.hpp"
#include "cppa/uniform_type_info.hpp" #include "cppa/uniform_type_info.hpp"
...@@ -27,8 +26,6 @@ using std::endl; ...@@ -27,8 +26,6 @@ using std::endl;
using namespace cppa; using namespace cppa;
size_t test__tuple() size_t test__tuple()
{ {
CPPA_TEST(test__tuple); CPPA_TEST(test__tuple);
...@@ -42,7 +39,9 @@ size_t test__tuple() ...@@ -42,7 +39,9 @@ size_t test__tuple()
CPPA_CHECK_EQUAL(t0_0, "1"); CPPA_CHECK_EQUAL(t0_0, "1");
CPPA_CHECK_EQUAL(t0_1, 2); CPPA_CHECK_EQUAL(t0_1, 2);
// create a view of t0 that only contains the string // create a view of t0 that only contains the string
auto v0 = get_view<std::string, anything>(t0); auto v0opt = tuple_cast(t0, pattern<std::string, anything>());
if (!v0opt) throw std::runtime_error("tuple_cast failed!");
auto& v0 = *v0opt;
auto v0_0 = get<0>(v0); auto v0_0 = get<0>(v0);
CPPA_CHECK_EQUAL(v0.size(), 1); CPPA_CHECK_EQUAL(v0.size(), 1);
CPPA_CHECK((std::is_same<decltype(v0_0), std::string>::value)); CPPA_CHECK((std::is_same<decltype(v0_0), std::string>::value));
...@@ -57,5 +56,6 @@ size_t test__tuple() ...@@ -57,5 +56,6 @@ size_t test__tuple()
auto lhs = make_tuple(1,2,3,4); auto lhs = make_tuple(1,2,3,4);
auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4); auto rhs = make_tuple(static_cast<std::uint8_t>(1), 2.0, 3, 4);
CPPA_CHECK_EQUAL(lhs, rhs); CPPA_CHECK_EQUAL(lhs, rhs);
CPPA_CHECK_EQUAL(rhs, lhs);
return CPPA_TEST_RESULT; return CPPA_TEST_RESULT;
} }
...@@ -15,7 +15,6 @@ ...@@ -15,7 +15,6 @@
#include "test.hpp" #include "test.hpp"
#include "cppa/get_view.hpp"
#include "cppa/announce.hpp" #include "cppa/announce.hpp"
#include "cppa/serializer.hpp" #include "cppa/serializer.hpp"
#include "cppa/deserializer.hpp" #include "cppa/deserializer.hpp"
......
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