Commit b27b52d6 authored by neverlord's avatar neverlord

tuple_cast

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