// Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information. #pragma once /*! \file rx-map.hpp \brief For each item from this observable use Selector to produce an item to emit from the new observable that is returned. \tparam Selector the type of the transforming function \param s the selector function \return Observable that emits the items from the source observable, transformed by the specified function. \sample \snippet map.cpp map sample \snippet output.txt map sample */ #if !defined(RXCPP_OPERATORS_RX_MAP_HPP) #define RXCPP_OPERATORS_RX_MAP_HPP #include "../rx-includes.hpp" namespace rxcpp { namespace operators { namespace detail { template struct map_invalid_arguments {}; template struct map_invalid : public rxo::operator_base> { using type = observable, map_invalid>; }; template using map_invalid_t = typename map_invalid::type; template struct map { typedef rxu::decay_t source_value_type; typedef rxu::decay_t select_type; typedef decltype((*(select_type*)nullptr)(*(source_value_type*)nullptr)) value_type; select_type selector; map(select_type s) : selector(std::move(s)) { } template struct map_observer { typedef map_observer this_type; typedef decltype((*(select_type*)nullptr)(*(source_value_type*)nullptr)) value_type; typedef rxu::decay_t dest_type; typedef observer observer_type; dest_type dest; mutable select_type selector; map_observer(dest_type d, select_type s) : dest(std::move(d)) , selector(std::move(s)) { } template void on_next(Value&& v) const { auto selected = on_exception( [&](){ return this->selector(std::forward(v));}, dest); if (selected.empty()) { return; } dest.on_next(std::move(selected.get())); } void on_error(rxu::error_ptr e) const { dest.on_error(e); } void on_completed() const { dest.on_completed(); } static subscriber make(dest_type d, select_type s) { auto cs = d.get_subscription(); return make_subscriber(std::move(cs), observer_type(this_type(std::move(d), std::move(s)))); } }; template auto operator()(Subscriber dest) const -> decltype(map_observer::make(std::move(dest), selector)) { return map_observer::make(std::move(dest), selector); } }; } /*! @copydoc rx-map.hpp */ template auto map(AN&&... an) -> operator_factory { return operator_factory(std::make_tuple(std::forward(an)...)); } /*! @copydoc rx-map.hpp */ template auto transform(AN&&... an) -> operator_factory { return operator_factory(std::make_tuple(std::forward(an)...)); } } template<> struct member_overload { template>, class ResolvedSelector = rxu::decay_t, class SourceValue = rxu::value_type_t, class Map = rxo::detail::map, class Value = rxu::value_type_t> static auto member(Observable&& o, Selector&& s) -> decltype(o.template lift(Map(std::forward(s)))) { return o.template lift(Map(std::forward(s))); } template static operators::detail::map_invalid_t member(const AN...) { std::terminate(); return {}; static_assert(sizeof...(AN) == 10000, "map takes Selector"); } }; } #endif