From f0b25956b91b4d702bf674943c1fefeeaafd16c4 Mon Sep 17 00:00:00 2001 From: Denis Blank Date: Tue, 6 Feb 2018 02:18:28 +0100 Subject: [PATCH] Implement the missing checks for container categories --- include/continuable/continuable-traverse.hpp | 20 ++++++------ .../continuable/detail/container-category.hpp | 32 +++++++++++++++++-- include/continuable/detail/traverse.hpp | 6 +--- 3 files changed, 40 insertions(+), 18 deletions(-) diff --git a/include/continuable/continuable-traverse.hpp b/include/continuable/continuable-traverse.hpp index ce11180..5356f39 100644 --- a/include/continuable/continuable-traverse.hpp +++ b/include/continuable/continuable-traverse.hpp @@ -71,19 +71,19 @@ namespace cti { /// template auto map_pack(Mapper&& mapper, T&&... pack) { - return detail::traversal::apply_pack_transform( - detail::traversal::strategy_remap_tag{}, std::forward(mapper), - std::forward(pack)...); + return detail::traversal::transform(detail::traversal::strategy_remap_tag{}, + std::forward(mapper), + std::forward(pack)...); } /// Indicate that the result shall be spread across the parent container /// if possible. This can be used to create a mapper function used /// in map_pack that maps one element to an arbitrary count (1:n). template -constexpr auto spread_this(T&&... args) { - return detail::traversal::spreading::spread_box< - typename std::decay::type...>( - std::make_tuple(std::forward(args)...)); +constexpr auto spread_this(T&&... args) noexcept( + noexcept(std::make_tuple(std::forward(args)...))) { + using type = detail::traversal::spreading::spread_box...>; + return type(std::make_tuple(std::forward(args)...)); } /// Traverses the pack with the given visitor. @@ -94,9 +94,9 @@ constexpr auto spread_this(T&&... args) { /// See `map_pack` for a detailed description. template void traverse_pack(Mapper&& mapper, T&&... pack) { - detail::traversal::apply_pack_transform( - detail::traversal::strategy_traverse_tag{}, std::forward(mapper), - std::forward(pack)...); + detail::traversal::transform(detail::traversal::strategy_traverse_tag{}, + std::forward(mapper), + std::forward(pack)...); } } // namespace cti diff --git a/include/continuable/detail/container-category.hpp b/include/continuable/detail/container-category.hpp index 2aea4c4..035a67c 100644 --- a/include/continuable/detail/container-category.hpp +++ b/include/continuable/detail/container-category.hpp @@ -31,9 +31,36 @@ #ifndef CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED #define CONTINUABLE_DETAIL_CONTAINER_CATEGORY_HPP_INCLUDED +#include +#include + +#include + namespace cti { namespace detail { namespace traversal { +namespace detail { +/// Deduces to a true type if the given parameter T +/// has a begin() and end() method. +// TODO Find out whether we should use std::begin and std::end instead, which +// could cause issues with plain arrays. +template +struct is_range : std::false_type {}; +template +struct is_range().begin() == + std::declval().end())>> + : std::true_type {}; + +/// Deduces to a true type if the given parameter T +/// is accessible through std::tuple_size. +template +struct is_tuple_like : std::false_type {}; +template +struct is_tuple_like::value)>> + : std::true_type {}; + +} // namespace detail + /// A tag for dispatching based on the tuple like /// or container properties of a type. template @@ -42,9 +69,8 @@ struct container_category_tag {}; /// Deduces to the container_category_tag of the given type T. template using container_category_of_t = - container_category_tag::value, - false // TODO traits::is_tuple_like::value - >; + container_category_tag::value, + detail::is_tuple_like::value>; } // namespace traversal } // namespace detail } // namespace cti diff --git a/include/continuable/detail/traverse.hpp b/include/continuable/detail/traverse.hpp index 60783fd..46ca3f8 100644 --- a/include/continuable/detail/traverse.hpp +++ b/include/continuable/detail/traverse.hpp @@ -833,11 +833,7 @@ public: /// Traverses the given pack with the given mapper and strategy template -auto apply_pack_transform(Strategy strategy, Mapper&& mapper, T&&... pack) - -> decltype( - std::declval< - mapping_helper::type>>() - .init_traverse(strategy, std::forward(pack)...)) { +auto transform(Strategy strategy, Mapper&& mapper, T&&... pack) { mapping_helper::type> helper( std::forward(mapper)); return helper.init_traverse(strategy, std::forward(pack)...);