/* /~` _ _ _|_. _ _ |_ | _ \_,(_)| | | || ||_|(_||_)|(/_ https://github.com/Naios/continuable v2.0.0 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. **/ #ifndef CONTINUABLE_DETAIL_TRAVERSE_HPP_INCLUDED #define CONTINUABLE_DETAIL_TRAVERSE_HPP_INCLUDED #include #include #include #include #include #include #include #include namespace cti { namespace detail { namespace traversal { /// Exposes useful facilities for dealing with 1:n mappings namespace spreading { /// A struct to mark a tuple to be unpacked into the parent context template class spread_box { std::tuple boxed_; public: explicit constexpr spread_box(std::tuple boxed) : boxed_(std::move(boxed)) { } std::tuple unbox() { return std::move(boxed_); } }; template <> class spread_box<> { public: explicit constexpr spread_box() noexcept { } explicit constexpr spread_box(std::tuple<>) noexcept { } constexpr std::tuple<> unbox() const noexcept { return std::tuple<>{}; } }; /// Returns an empty spread box which represents an empty /// mapped object. constexpr spread_box<> empty_spread() noexcept { return spread_box<>{}; } /// Deduces to a true_type if the given type is a spread marker template struct is_spread : std::false_type {}; template struct is_spread> : std::true_type {}; /// Deduces to a true_type if the given type is an empty /// spread marker template struct is_empty_spread : std::false_type {}; template <> struct is_empty_spread> : std::true_type {}; /// Converts types to the type and spread_box objects to its /// underlying tuple. template constexpr T unpack(T&& type) { return std::forward(type); } template constexpr auto unpack(spread_box type) -> decltype(type.unbox()) { return type.unbox(); } /// Deduces to the type unpack is returning when called with the /// the given type T. template using unpacked_of_t = decltype(unpack(std::declval())); /// Converts types to the type and spread_box objects to its /// underlying tuple. If the type is mapped to zero elements, /// the return type will be void. template constexpr auto unpack_or_void(T&& type) -> decltype(unpack(std::forward(type))) { return unpack(std::forward(type)); } inline void unpack_or_void(spread_box<>) noexcept { } /// Converts types to the a tuple carrying the single type and /// spread_box objects to its underlying tuple. template constexpr std::tuple undecorate(T&& type) { return std::tuple{std::forward(type)}; } template constexpr auto undecorate(spread_box type) -> decltype(type.unbox()) { return type.unbox(); } /// A callable object which maps its content back to a /// tuple like type. template class Type> struct tupelizer_base { // We overload with one argument here so Clang and GCC don't // have any issues with overloading against zero arguments. template constexpr Type operator()(First&& first, T&&... args) const { return Type{std::forward(first), std::forward(args)...}; } // Specifically return the empty object which can be different // from a tuple. constexpr EmptyType operator()() const noexcept(noexcept(EmptyType{})) { return EmptyType{}; } }; /// A callable object which maps its content back to a tuple. template