/* Copyright(c) 2015 - 2018 Denis Blank Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files(the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and / or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions : The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. **/ #include #include #include #include #include // Devel #include #include namespace cti { namespace detail { /// This namespace provides utilities for performing compound /// connections between deeply nested continuables and values. /// /// 0. We create the result pack from the provides values and /// the async values if those are default constructible, /// otherwise use a lazy initialization wrapper and unwrap /// the whole pack when the composition is finished. /// - value -> value /// - single async value -> single value /// - multiple async value -> tuple of async values. /// /// 1. namespace remapping { // Guard object for representing void results struct void_result_guard {}; /// Contains an continuable together with a location where the /// result shall be stored. template struct indexed_continuable { Continuable continuable; Target* target; }; namespace detail { struct result_extractor_mapper { /// Create slots for a void result which is removed later. /// This is required due to the fact that each continuable has exactly /// one matching valuen inside the result tuple. static constexpr auto initialize(hints::signature_hint_tag<>) noexcept { return void_result_guard{}; } /// Initialize a single value template static constexpr auto initialize(hints::signature_hint_tag) { return First{}; } /// Initialize a multiple values as tuple template static constexpr auto initialize(hints::signature_hint_tag<>) { // TODO Fix non default constructible values return std::make_tuple(First{}, Second{}, Args{}...); } /// Remap a continuable to its corresponding result values /// A void result is mapped to a guard type, single values to the value /// itself and multiple ones to a tuple of values. template < typename T, std::enable_if_t>::value>* = nullptr> auto operator()(T&& /*continuable*/) { auto constexpr const hint = hints::hint_of(traits::identify{}); return initialize(hint); } }; /// Maps a deeply nested pack of continuables to struct result_indexer_mapper { /// Index a given continuable together with its target location template < typename T, std::enable_if_t>::value>* = nullptr> auto operator()(T&& continuable) { auto constexpr const hint = hints::hint_of(traits::identify{}); using target = decltype(result_extractor_mapper::initialize(hint)); using type = indexed_continuable, target>; return type{std::forward(continuable), nullptr}; } /// Remove all other non container values from this pack /*template < typename T, typename Category = traversal::container_category_of_t>, std::enable_if_t* = nullptr> auto operator()(T&&) { return spread_this(); }*/ }; } // namespace detail /// Returns the result pack of the given deeply nested pack. /// This invalidates all non-continuable values contained inside the pack. /// /// This consumes all non continuables inside the pack. template constexpr auto create_result_pack(Args&&... args) { return cti::map_pack(detail::result_extractor_mapper{}, std::forward(args)...); } /// Returns the result pack of the given deeply nested pack. /// This invalidates all non-continuable values contained inside the pack. /// /// This consumes all continuables inside the pack. template constexpr auto create_index_pack(Args&&... args) { return cti::map_pack(detail::result_indexer_mapper{}, std::forward(args)...); } /// Sets the target pointers of indexed_continuable's inside the index pack /// to point to their given counterparts inside the given target. template constexpr auto relocate_index_pack(Index* index, Target* target) { /*return cti::map_pack(detail::result_indexer_mapper{}, std::forward(args)...);*/ } /* template auto remape_container(traversal::container_category_tag, T&& container) { } template auto remape_container(traversal::container_category_tag, T&& container) { } template < typename T, typename Category = traversal::container_category_of_t>, std::enable_if_t* = nullptr> auto operator()(T&& container) { return remape_container(std::forward(container)); } */ } // namespace remapping struct c {}; template struct loc {}; struct runtime_insertion { std::size_t begin, end; }; template struct future_result { std::tuple result_; }; } // namespace detail } // namespace cti using namespace cti::detail::remapping; int main(int, char**) { using namespace cti::detail; std::vector vc{1, 2, 3}; // std::tuple t; // std::tuple>, c, c> loc; auto p = std::make_tuple(0, 4, cti::make_ready_continuable(0), std::make_tuple(1, 2), cti::make_ready_continuable(0)); auto r = create_result_pack(std::move(p)); auto i = create_index_pack(std::move(p)); return 0; }