/* 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; }; template struct is_indexed_continuable : std::false_type {}; template struct is_indexed_continuable> : std::true_type {}; 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}; } }; /// Relocates the target of a deeply nested pack of indexed_continuable objects /// to the given target. template struct result_relocator_mapper { Evaluator evaluator; template void traverse_one(std::false_type, Index*, Result*) { // Don't do anything when dealing with casual objects } template void traverse_one(std::true_type, Index* index, Result* result) { // Call the evaluator with the address of the indexed object and its target evaluator(index, result); } template void traverse(traversal::container_category_tag, Index* index, Result* result) { auto id = traits::identity>{}; auto i = is_indexed_continuable>::value; auto res = traits::is_invocable{}; evaluator(index, result); traverse_one(traits::is_invocable{}, index, result); } /// Traverse a homogeneous container template void traverse(traversal::container_category_tag, Index* index, Result* result) { auto index_itr = index->begin(); auto const index_end = index->end(); auto result_itr = result->begin(); auto const result_end = result->end(); using element_t = std::decay_tbegin())>; traversal::container_category_of_t constexpr const tag; for (; index_itr != index_end; ++index_itr, ++result_itr) { assert(result_itr != result_end); traverse(tag, &*index_itr, &*result_itr); } } template void traverse_tuple_like(std::integer_sequence, Index* index, Result* result) { (void)std::initializer_list{( (void)traverse( traversal::container_category_of_t(*index))>{}, &std::get(*index), &std::get(*result)), 0)...}; } /// Traverse tuple like container template void traverse(traversal::container_category_tag, Index* index, Result* result) { std::make_index_sequence::value> constexpr const i{}; traverse_tuple_like(i, index, result); } }; } // 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 void relocate_index_pack(Relocator&& relocator, Index* index, Target* target) { constexpr traversal::container_category_of_t const tag; detail::result_relocator_mapper> mapper{ std::forward(relocator)}; mapper.traverse(tag, index, target); } /* 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(cti::make_ready_continuable(0) /*, 0, 4, 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)); /*relocate_index_pack( [](auto index, auto result) -> std::enable_if_t>>::value> { // Assign the address of the target to the indexed continuable index->target = result; return; }, &i, &r);*/ auto t = [](auto&&...) {}; promisify::from(t, ""); return 0; }