Revert 5dfe388f7f8156

* It turns out that this isn't needed anymore and just affects
  the compile time by now
* Additionally GCC can't handle this properly
This commit is contained in:
Denis Blank 2018-03-02 02:51:53 +01:00
parent 178f590aa9
commit dd1b605d95
2 changed files with 46 additions and 79 deletions

View File

@ -215,7 +215,6 @@ constexpr auto map_spread(C&& callable, T&&... args)
-> decltype(apply_spread_impl(is_any_spread_t<T...>{}, -> decltype(apply_spread_impl(is_any_spread_t<T...>{},
std::forward<C>(callable), std::forward<C>(callable),
std::forward<T>(args)...)) { std::forward<T>(args)...)) {
// Check whether any of the args is a detail::flatted_tuple_t, // Check whether any of the args is a detail::flatted_tuple_t,
// if not, use the linear called version for better // if not, use the linear called version for better
// compilation speed. // compilation speed.
@ -692,10 +691,20 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
return mapper_(std::forward<T>(element)); return mapper_(std::forward<T>(element));
} }
/// SFINAE helper for plain elements not satisfying the tuple like
/// or container requirements.
///
/// We use the proxy function invoke_mapper here,
/// because some compilers (MSVC) tend to instantiate the invocation
/// before matching the tag, which leads to build failures.
template <typename T>
auto match(container_category_tag<false, false>, T&& element) -> decltype(
std::declval<mapping_helper>().invoke_mapper(std::forward<T>(element)));
/// SFINAE helper for elements satisfying the container /// SFINAE helper for elements satisfying the container
/// requirements, which are not tuple like. /// requirements, which are not tuple like.
template <typename T> template <typename T>
auto deep_map(container_category_tag<true, false>, T&& container) auto match(container_category_tag<true, false>, T&& container)
-> decltype(container_remapping::remap(Strategy{}, -> decltype(container_remapping::remap(Strategy{},
std::forward<T>(container), std::forward<T>(container),
std::declval<traversor>())); std::declval<traversor>()));
@ -703,33 +712,42 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
/// SFINAE helper for elements which are tuple like and /// SFINAE helper for elements which are tuple like and
/// that also may satisfy the container requirements /// that also may satisfy the container requirements
template <bool IsContainer, typename T> template <bool IsContainer, typename T>
auto deep_map(container_category_tag<IsContainer, true>, T&& tuple_like) auto match(container_category_tag<IsContainer, true>, T&& tuple_like)
-> decltype(tuple_like_remapping::remap(Strategy{}, -> decltype(tuple_like_remapping::remap(Strategy{},
std::forward<T>(tuple_like), std::forward<T>(tuple_like),
std::declval<traversor>())); std::declval<traversor>()));
/// SFINAE helper for plain elements not satisfying the tuple like /// This method implements the functionality for routing
/// or container requirements. /// elements through, that aren't accepted by the mapper.
/// Since the real matcher methods below are failing through SFINAE,
/// the compiler will try to specialize this function last,
/// since it's the least concrete one.
/// This works recursively, so we only call the mapper
/// with the minimal needed set of accepted arguments.
template <typename MatcherTag, typename T>
auto try_match(MatcherTag, T&& element) -> decltype(
std::declval<mapping_helper>().may_void(std::forward<T>(element))) {
return this->may_void(std::forward<T>(element));
}
/// Match plain elements not satisfying the tuple like or
/// container requirements.
/// ///
/// We use the proxy function invoke_mapper here, /// We use the proxy function invoke_mapper here,
/// because some compilers (MSVC) tend to instantiate the invocation /// because some compilers (MSVC) tend to instantiate the invocation
/// before matching the tag, which leads to build failures. /// before matching the tag, which leads to build failures.
template <bool IsContainer, bool IsTupleLike, typename T> template <typename T>
auto map(container_category_tag<IsContainer, IsTupleLike>, T&& element) auto try_match(container_category_tag<false, false>, T&& element) -> decltype(
-> decltype(std::declval<mapping_helper>().invoke_mapper( std::declval<mapping_helper>().invoke_mapper(std::forward<T>(element))) {
std::forward<T>(element))); // T could be any non container or non tuple like type here,
// take int or hpx::future<int> as an example.
/// SFINAE helper for forwarding the input to the deep remap methods in order return invoke_mapper(std::forward<T>(element));
/// to prioritize the mapper before deep container remaps. }
template <typename Category, typename T>
auto map(Category category, T&& element)
-> decltype(std::declval<mapping_helper>().deep_map(
category, std::forward<T>(element)));
/// Match elements satisfying the container requirements, /// Match elements satisfying the container requirements,
/// which are not tuple like. /// which are not tuple like.
template <typename T> template <typename T>
auto try_deep_map(container_category_tag<true, false>, T&& container) auto try_match(container_category_tag<true, false>, T&& container)
-> decltype(container_remapping::remap(Strategy{}, -> decltype(container_remapping::remap(Strategy{},
std::forward<T>(container), std::forward<T>(container),
std::declval<try_traversor>())) { std::declval<try_traversor>())) {
@ -741,7 +759,7 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
/// satisfy the container requirements /// satisfy the container requirements
/// -> We match tuple like types over container like ones /// -> We match tuple like types over container like ones
template <bool IsContainer, typename T> template <bool IsContainer, typename T>
auto try_deep_map(container_category_tag<IsContainer, true>, T&& tuple_like) auto try_match(container_category_tag<IsContainer, true>, T&& tuple_like)
-> decltype(tuple_like_remapping::remap(Strategy{}, -> decltype(tuple_like_remapping::remap(Strategy{},
std::forward<T>(tuple_like), std::forward<T>(tuple_like),
std::declval<try_traversor>())) { std::declval<try_traversor>())) {
@ -749,63 +767,27 @@ class mapping_helper : protected mapping_strategy_base<Strategy> {
try_traversor{this}); try_traversor{this});
} }
/// This method implements the functionality for routing
/// elements through, that aren't accepted by the mapper.
/// Since the real matcher methods below are failing through SFINAE,
/// the compiler will try to specialize this function last,
/// since it's the least concrete one.
/// This works recursively, so we only call the mapper
/// with the minimal needed set of accepted arguments.
template <typename MatcherTag, typename T>
auto try_deep_map(MatcherTag, T&& element) -> decltype(
std::declval<mapping_helper>().may_void(std::forward<T>(element))) {
return this->may_void(std::forward<T>(element));
}
/// Prioritize the mapper over container remapping.
///
/// We use the proxy function invoke_mapper here,
/// because some compilers (MSVC) tend to instantiate the invocation
/// before matching the tag, which leads to build failures.
template <bool IsContainer, bool IsTupleLike, typename T>
auto try_map(container_category_tag<IsContainer, IsTupleLike>, T&& element)
-> decltype(std::declval<mapping_helper>().invoke_mapper(
std::forward<T>(element))) {
// T could be any non container or non tuple like type here,
// take int or std::future<int> as an example.
return invoke_mapper(std::forward<T>(element));
}
/// Forward the input to the deep remap methods in order
/// to prioritize the mapper before deep container remaps.
template <typename Category, typename T>
auto try_map(Category category, T&& element)
-> decltype(std::declval<mapping_helper>().try_deep_map(
category, std::forward<T>(element))) {
return try_deep_map(category, std::forward<T>(element));
}
/// Traverses a single element. /// Traverses a single element.
/// ///
/// SFINAE helper: Doesn't allow routing through elements, /// SFINAE helper: Doesn't allow routing through elements,
/// that aren't accepted by the mapper /// that aren't accepted by the mapper
template <typename T> template <typename T>
auto traverse(Strategy, T&& element) auto traverse(Strategy, T&& element)
-> decltype(std::declval<mapping_helper>().map( -> decltype(std::declval<mapping_helper>().match(
std::declval<container_category_of_t<typename std::decay<T>::type>>(), std::declval<container_category_of_t<typename std::decay<T>::type>>(),
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_map( -> decltype(std::declval<mapping_helper>().try_match(
std::declval<container_category_of_t<typename std::decay<T>::type>>(), std::declval<container_category_of_t<typename std::decay<T>::type>>(),
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_map(container_category_of_t<typename std::decay<T>::type>{}, return try_match(container_category_of_t<typename std::decay<T>::type>{},
std::forward<T>(element)); std::forward<T>(element));
} }
public: public:

View File

@ -44,9 +44,7 @@ using cti::spread_this;
using cti::traverse_pack; using cti::traverse_pack;
struct all_map_float { struct all_map_float {
template < template <typename T>
typename T,
std::enable_if_t<std::is_arithmetic<std::decay_t<T>>::value>* = nullptr>
float operator()(T el) const { float operator()(T el) const {
return float(el + 1.f); return float(el + 1.f);
} }
@ -61,7 +59,8 @@ struct my_mapper {
}; };
struct all_map { struct all_map {
int operator()(int) const { template <typename T>
int operator()(T) const {
return 0; return 0;
} }
}; };
@ -281,9 +280,7 @@ public:
explicit counter_mapper(int& counter) : counter_(counter) { explicit counter_mapper(int& counter) : counter_(counter) {
} }
template <typename T, template <typename T>
std::enable_if_t<std::is_arithmetic<std::decay_t<T>>::value ||
std::is_empty<std::decay_t<T>>::value>* = nullptr>
void operator()(T) const { void operator()(T) const {
++counter_.get(); ++counter_.get();
} }
@ -680,7 +677,8 @@ TEST(traverse_strategic_tuple_like_traverse, remap_references) {
/// A mapper which duplicates the given element /// A mapper which duplicates the given element
struct duplicate_mapper { struct duplicate_mapper {
auto operator()(int arg) -> decltype(spread_this(arg, arg)) { template <typename T>
auto operator()(T arg) -> decltype(spread_this(arg, arg)) {
return spread_this(arg, arg); return spread_this(arg, arg);
} }
}; };
@ -758,19 +756,6 @@ TEST(traverse_spread_tuple_like_traverse, one_to_zero_mapping_array) {
static_assert(std::is_void<Result>::value, "Failed..."); static_assert(std::is_void<Result>::value, "Failed...");
} }
TEST(traversal_prio, prioritize_mapping) {
std::vector<int> vec{0, 1, 2};
int res = map_pack(
[](std::vector<int>& vec) {
// ...
EXPECT_EQ(vec.size(), 3U);
return 4;
},
vec);
EXPECT_EQ(res, 4);
}
struct flat_tupelizing_tag1 {}; struct flat_tupelizing_tag1 {};
struct flat_tupelizing_tag2 {}; struct flat_tupelizing_tag2 {};