Started on transitioning to unref

This commit is contained in:
Denis Blank 2018-11-18 19:00:38 +01:00
parent a9d4ee5ba8
commit d62eec2632
3 changed files with 36 additions and 34 deletions

View File

@ -97,10 +97,10 @@ public:
/// given iterator tuple. /// given iterator tuple.
template <typename Frame, typename State> template <typename Frame, typename State>
auto make_resume_traversal_callable(Frame&& frame, State&& state) auto make_resume_traversal_callable(Frame&& frame, State&& state)
-> resume_traversal_callable<typename std::decay<Frame>::type, -> resume_traversal_callable<traits::unref_t<Frame>,
typename std::decay<State>::type> { traits::unref_t<State>> {
return resume_traversal_callable<typename std::decay<Frame>::type, return resume_traversal_callable<traits::unref_t<Frame>,
typename std::decay<State>::type>( traits::unref_t<State>>(
std::forward<Frame>(frame), std::forward<State>(state)); std::forward<Frame>(frame), std::forward<State>(state));
} }
@ -292,8 +292,8 @@ struct dynamic_async_range {
template <typename T> template <typename T>
using dynamic_async_range_of_t = dynamic_async_range< using dynamic_async_range_of_t = dynamic_async_range<
typename std::decay<decltype(std::begin(std::declval<T>()))>::type, traits::unref_t<decltype(std::begin(std::declval<T>()))>,
typename std::decay<decltype(std::end(std::declval<T>()))>::type>; traits::unref_t<decltype(std::end(std::declval<T>()))>>;
/// Returns a dynamic range for the given type /// Returns a dynamic range for the given type
template <typename T> template <typename T>
@ -337,9 +337,8 @@ public:
auto hierarchy = std::tuple_cat( auto hierarchy = std::tuple_cat(
std::make_tuple(std::forward<Parent>(parent)), hierarchy_); std::make_tuple(std::forward<Parent>(parent)), hierarchy_);
return async_traversal_point<Frame, typename std::decay<Parent>::type, return async_traversal_point<Frame, traits::unref_t<Parent>, Hierarchy...>(
Hierarchy...>(frame_, std::move(hierarchy), frame_, std::move(hierarchy), detached_);
detached_);
} }
/// Forks the current traversal point and continues the child /// Forks the current traversal point and continues the child
@ -405,7 +404,7 @@ public:
/// Async traverse the current iterator /// Async traverse the current iterator
template <typename Current> template <typename Current>
void async_traverse_one(Current&& current) { void async_traverse_one(Current&& current) {
using ElementType = typename std::decay<decltype(*current)>::type; using ElementType = traits::unref_t<decltype(*current)>;
return async_traverse_one_impl(container_category_of_t<ElementType>{}, return async_traverse_one_impl(container_category_of_t<ElementType>{},
std::forward<Current>(current)); std::forward<Current>(current));
} }
@ -453,8 +452,8 @@ public:
/// given frame and hierarchy /// given frame and hierarchy
template <typename Frame, typename... Hierarchy> template <typename Frame, typename... Hierarchy>
using traversal_point_of_t = using traversal_point_of_t =
async_traversal_point<typename std::decay<Frame>::type, async_traversal_point<traits::unref_t<Frame>,
typename std::decay<Hierarchy>::type...>; traits::unref_t<Hierarchy>...>;
/// A callable object which is capable of resuming an asynchronous /// A callable object which is capable of resuming an asynchronous
/// pack traversal. /// pack traversal.
@ -528,8 +527,8 @@ template <typename Visitor, typename... Args>
struct async_traversal_types { struct async_traversal_types {
/// Deduces to the async traversal frame type of the given /// Deduces to the async traversal frame type of the given
/// traversal arguments and mapper /// traversal arguments and mapper
using frame_t = async_traversal_frame<typename std::decay<Visitor>::type, using frame_t =
typename std::decay<Args>::type...>; async_traversal_frame<traits::unref_t<Visitor>, traits::unref_t<Args>...>;
/// The type of the demoted visitor type /// The type of the demoted visitor type
using visitor_t = Visitor; using visitor_t = Visitor;

View File

@ -169,8 +169,7 @@ struct flat_arraylizer {
/// Deduces to the array type when the array is instantiated /// Deduces to the array type when the array is instantiated
/// with the given arguments. /// with the given arguments.
template <typename First, typename... Rest> template <typename First, typename... Rest>
using array_type_of_t = using array_type_of_t = Type<traits::unref_t<First>, 1 + sizeof...(Rest)>;
Type<typename std::decay<First>::type, 1 + sizeof...(Rest)>;
// We overload with one argument here so Clang and GCC don't // We overload with one argument here so Clang and GCC don't
// have any issues with overloading against zero arguments. // have any issues with overloading against zero arguments.
@ -408,8 +407,8 @@ using element_of_t = typename std::conditional<
/// if the type is a l-value or r-value reference. /// if the type is a l-value or r-value reference.
template <typename T> template <typename T>
using dereferenced_of_t = using dereferenced_of_t =
typename std::conditional<std::is_reference<T>::value, typename std::conditional<std::is_reference<T>::value, traits::unref_t<T>,
typename std::decay<T>::type, T>::type; T>::type;
/// Returns the type which is resulting if the mapping is applied to /// Returns the type which is resulting if the mapping is applied to
/// an element in the container. /// an element in the container.
@ -423,8 +422,8 @@ using mapped_type_from_t = dereferenced_of_t<spreading::unpacked_of_t<decltype(
/// Deduces to a true_type if the mapping maps to zero elements. /// Deduces to a true_type if the mapping maps to zero elements.
template <typename T, typename M> template <typename T, typename M>
using is_empty_mapped = spreading::is_empty_spread<typename std::decay<decltype( using is_empty_mapped = spreading::is_empty_spread<traits::unref_t<decltype(
std::declval<M>()(std::declval<element_of_t<T>>()))>::type>; std::declval<M>()(std::declval<element_of_t<T>>()))>>;
/// We are allowed to reuse the container if we map to the same /// We are allowed to reuse the container if we map to the same
/// type we are accepting and when we have /// type we are accepting and when we have
@ -472,10 +471,9 @@ template <typename M, typename T>
auto remap_container(container_mapping_tag<false, false>, M&& mapper, auto remap_container(container_mapping_tag<false, false>, M&& mapper,
T&& container) T&& container)
-> decltype(rebind_container<mapped_type_from_t<T, M>>(container)) { -> decltype(rebind_container<mapped_type_from_t<T, M>>(container)) {
static_assert( static_assert(has_push_back<traits::unref_t<T>, element_of_t<T>>::value,
has_push_back<typename std::decay<T>::type, element_of_t<T>>::value, "Can only remap containers that provide a push_back "
"Can only remap containers that provide a push_back " "method!");
"method!");
// Create the new container, which is capable of holding // Create the new container, which is capable of holding
// the remappped types. // the remappped types.
@ -503,7 +501,7 @@ auto remap_container(container_mapping_tag<false, false>, M&& mapper,
/// type we accepted such as int -> int. /// type we accepted such as int -> int.
template <typename M, typename T> template <typename M, typename T>
auto remap_container(container_mapping_tag<false, true>, M&& mapper, auto remap_container(container_mapping_tag<false, true>, M&& mapper,
T&& container) -> typename std::decay<T>::type { T&& container) -> traits::unref_t<T> {
for (auto&& val : container_accessor_of(std::forward<T>(container))) { for (auto&& val : container_accessor_of(std::forward<T>(container))) {
val = spreading::unpack( val = spreading::unpack(
std::forward<M>(mapper)(std::forward<decltype(val)>(val))); std::forward<M>(mapper)(std::forward<decltype(val)>(val)));
@ -629,12 +627,11 @@ struct tuple_like_remapper<
/// different types. /// different types.
template <typename Strategy, typename T, typename M> template <typename Strategy, typename T, typename M>
auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack( auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack(
std::declval<tuple_like_remapper<Strategy, typename std::decay<M>::type, std::declval<tuple_like_remapper<Strategy, traits::unref_t<M>,
typename std::decay<T>::type>>(), traits::unref_t<T>>>(),
std::forward<T>(container))) { std::forward<T>(container))) {
return traits::unpack( return traits::unpack(
tuple_like_remapper<Strategy, typename std::decay<M>::type, tuple_like_remapper<Strategy, traits::unref_t<M>, traits::unref_t<T>>{
typename std::decay<T>::type>{
std::forward<M>(mapper)}, std::forward<M>(mapper)},
std::forward<T>(container)); std::forward<T>(container));
} }
@ -645,7 +642,7 @@ auto remap(Strategy, T&& container, M&& mapper) -> decltype(traits::unpack(
template <typename Strategy> template <typename Strategy>
struct mapping_strategy_base { struct mapping_strategy_base {
template <typename T> template <typename T>
auto may_void(T&& element) const -> typename std::decay<T>::type { auto may_void(T&& element) const -> traits::unref_t<T> {
return std::forward<T>(element); return std::forward<T>(element);
} }
}; };
@ -803,19 +800,19 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
template <typename T> template <typename T>
auto traverse(Strategy, T&& element) auto traverse(Strategy, T&& element)
-> decltype(std::declval<mapping_helper>().match( -> decltype(std::declval<mapping_helper>().match(
std::declval<container_category_of_t<typename std::decay<T>::type>>(), std::declval<container_category_of_t<traits::unref_t<T>>>(),
std::declval<T>())); std::declval<T>()));
/// \copybrief traverse /// \copybrief traverse
template <typename T> template <typename T>
auto try_traverse(Strategy, T&& element) auto try_traverse(Strategy, T&& element)
-> decltype(std::declval<mapping_helper>().try_match( -> decltype(std::declval<mapping_helper>().try_match(
std::declval<container_category_of_t<typename std::decay<T>::type>>(), std::declval<container_category_of_t<traits::unref_t<T>>>(),
std::declval<T>())) { std::declval<T>())) {
// We use tag dispatching here, to categorize the type T whether // We use tag dispatching here, to categorize the type T whether
// it satisfies the container or tuple like requirements. // it satisfies the container or tuple like requirements.
// Then we can choose the underlying implementation accordingly. // Then we can choose the underlying implementation accordingly.
return try_match(container_category_of_t<typename std::decay<T>::type>{}, return try_match(container_category_of_t<traits::unref_t<T>>{},
std::forward<T>(element)); std::forward<T>(element));
} }
@ -861,7 +858,7 @@ public:
/// Traverses the given pack with the given mapper and strategy /// Traverses the given pack with the given mapper and strategy
template <typename Strategy, typename Mapper, typename... T> template <typename Strategy, typename Mapper, typename... T>
decltype(auto) transform(Strategy strategy, Mapper&& mapper, T&&... pack) { decltype(auto) transform(Strategy strategy, Mapper&& mapper, T&&... pack) {
mapping_helper<Strategy, typename std::decay<Mapper>::type> helper( mapping_helper<Strategy, traits::unref_t<Mapper>> helper(
std::forward<Mapper>(mapper)); std::forward<Mapper>(mapper));
return helper.init_traverse(strategy, std::forward<T>(pack)...); return helper.init_traverse(strategy, std::forward<T>(pack)...);
} }

View File

@ -40,6 +40,12 @@
namespace cti { namespace cti {
namespace detail { namespace detail {
namespace traits { namespace traits {
/// Removes all references and qualifiers from the given type T,
/// since traits::unref_t has too much overhead through checking for
/// function pointers and arrays.
template <typename T>
using unref_t = std::remove_cv_t<std::remove_reference_t<T>>;
namespace detail { namespace detail {
template <typename T, typename... Args> template <typename T, typename... Args>
struct index_of_impl; struct index_of_impl;