Commit c0d66981 authored by neverlord's avatar neverlord

added unsafe tuple cast that skips type checking

parent c6f9dc0a
......@@ -52,24 +52,50 @@ enum class tuple_cast_impl_id
};
// covers wildcard_in_between and multiple_wildcards
template<wildcard_position, class Result, typename... T>
template<wildcard_position WP, class Result, typename... T>
struct tuple_cast_impl
{
static constexpr size_t size =
util::tl_count_not<util::type_list<T...>, is_anything>::value;
static constexpr size_t first_wc =
static_cast<size_t>(util::tl_find<util::type_list<T...>, anything>::value);
typedef util::fixed_vector<size_t, size> mapping_vector;
template<class Tuple>
inline static option<Result> _(Tuple const& tup)
static inline option<Result> safe(Tuple const& tup)
{
mapping_vector mv;
if (match<T...>(tup, mv)) return {Result::from(tup.vals(), mv)};
return {};
}
template<class Tuple>
inline static option<Result> _(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
{
mapping_vector mv;
if (match(tup, p)) return {Result::from(tup.vals(), mv)};
if (match(tup, p, mv)) return {Result::from(tup.vals(), mv)};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
{
mapping_vector mv;
if (WP == wildcard_position::in_between)
{
if (!p.has_values() || matcher<WP, T...>::vmatch(tup, p))
{
// first range
mv.resize(size);
auto begin = mv.begin();
std::iota(begin, begin + first_wc, 0);
// second range
begin = mv.begin() + first_wc;
std::iota(begin, mv.end(), tup.size() - (size - first_wc));
return {Result::from(tup.vals(), mv)};
}
}
else
{
if (match(tup, p, mv)) return {Result::from(tup.vals(), mv)};
}
return {};
}
};
......@@ -78,42 +104,73 @@ template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::nil, Result, T...>
{
template<class Tuple>
static inline option<Result> _(Tuple const& tup)
static inline option<Result> safe(Tuple const& tup)
{
if (match<T...>(tup)) return {Result::from(tup.vals())};
return {};
}
template<class Tuple>
static inline option<Result> _(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
{
if (match(tup, p)) return {Result::from(tup.vals())};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::nil, T...>::vmatch(tup, p))
{
return {Result::from(tup.vals())};
}
return {};
}
};
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::trailing, Result, T...>
: tuple_cast_impl<wildcard_position::nil, Result, T...>
{
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::trailing, T...>::vmatch(tup, p))
{
return {Result::from(tup.vals())};
}
return {};
}
};
template<class Result, typename... T>
struct tuple_cast_impl<wildcard_position::leading, Result, T...>
{
template<class Tuple>
inline static option<Result> _(Tuple const& tup)
static inline option<Result> safe(Tuple const& tup)
{
size_t o = tup.size() - (sizeof...(T) - 1);
if (match<T...>(tup)) return {Result::offset_subtuple(tup.vals(), o)};
return {};
}
template<class Tuple>
inline static option<Result> _(Tuple const& tup, pattern<T...> const& p)
static inline option<Result> safe(Tuple const& tup, pattern<T...> const& p)
{
size_t o = tup.size() - (sizeof...(T) - 1);
if (match(tup, p)) return {Result::offset_subtuple(tup.vals(), o)};
return {};
}
template<class Tuple>
static inline option<Result> unsafe(Tuple const& tup, pattern<T...> const& p)
{
if ( p.has_values() == false
|| matcher<wildcard_position::leading, T...>::vmatch(tup, p))
{
size_t o = tup.size() - (sizeof...(T) - 1);
return Result::offset_subtuple(tup.vals(), o);
}
return {};
}
};
} }
......
......@@ -53,7 +53,7 @@ auto tuple_cast(any_tuple const& tup, pattern<T...> const& p)
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup, p);
return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup, p);
}
// cast using types
......@@ -69,7 +69,24 @@ auto tuple_cast(any_tuple const& tup)
typedef typename result_type::value_type tuple_type;
static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::_(tup);
return detail::tuple_cast_impl<impl, tuple_type, T...>::safe(tup);
}
/////////////////////////// for in-library use only! ///////////////////////////
// cast using a pattern; does not perform type checking
template<typename... T>
auto unsafe_tuple_cast(any_tuple const& tup, pattern<T...> const& p)
-> option<
typename tuple_from_type_list<
typename pattern<T...>::filtered_types
>::type>
{
typedef typename pattern<T...>::filtered_types filtered_types;
typedef typename tuple_from_type_list<filtered_types>::type tuple_type;
static constexpr auto impl =
get_wildcard_position<util::type_list<T...>>();
return detail::tuple_cast_impl<impl, tuple_type, T...>::unsafe(tup, p);
}
} // namespace cppa
......
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