Created
September 28, 2025 09:41
-
-
Save Morwenn/ed6af6fc1185d0dc591c51fef8407d43 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * Copyright (c) 2025 Morwenn | |
| * SPDX-License-Identifier: CC0-1.0 | |
| */ | |
| // Make an std::index_sequence in reverse order | |
| template<std::size_t Index, std::size_t... Indices> | |
| struct make_reversed_index_sequence: | |
| make_reversed_index_sequence<Index - 1, Indices..., Index - 1> | |
| {}; | |
| template<std::size_t... Indices> | |
| struct make_reversed_index_sequence<0, Indices...>: | |
| std::index_sequence<Indices...> | |
| {}; | |
| // Type returned by flip | |
| template<typename F> | |
| struct flip_t | |
| { | |
| private: | |
| F func; | |
| // Forward *this cv-ref and invert order of parameters | |
| template<typename Self, typename Tuple, std::size_t... Indices> | |
| static auto _call(Self&& self, Tuple&& args, std::index_sequence<Indices...>) | |
| -> decltype(std::invoke( | |
| std::forward<Self>(self).func, | |
| std::get<Indices>(std::forward<Tuple>(args))... | |
| )) | |
| { | |
| return std::invoke( | |
| std::forward<Self>(self).func, | |
| std::get<Indices>(std::forward<Tuple>(args))... | |
| ); | |
| } | |
| template<typename Self, typename Tuple> | |
| static auto _call(Self&& self, Tuple&& args) | |
| -> decltype(_call( | |
| std::forward<Self>(self), | |
| std::forward<Tuple>(args), | |
| make_reversed_index_sequence<std::tuple_size_v<Tuple>>{} | |
| )) | |
| { | |
| return _call( | |
| std::forward<Self>(self), | |
| std::forward<Tuple>(args), | |
| make_reversed_index_sequence<std::tuple_size_v<Tuple>>{} | |
| ); | |
| } | |
| public: | |
| // Construction | |
| flip_t() = default; | |
| explicit constexpr flip_t(F&& func): | |
| func(std::move(func)) | |
| {} | |
| // Call | |
| template<typename... Args> | |
| constexpr auto operator()(Args&&... args) & | |
| -> decltype(_call(*this, std::forward_as_tuple(std::forward<Args>(args)...))) | |
| { | |
| return _call(*this, std::forward_as_tuple(std::forward<Args>(args)...)); | |
| } | |
| template<typename... Args> | |
| constexpr auto operator()(Args&&... args) const& | |
| -> decltype(_call(*this, std::forward_as_tuple(std::forward<Args>(args)...))) | |
| { | |
| return _call(*this, std::forward_as_tuple(std::forward<Args>(args)...)); | |
| } | |
| template<typename... Args> | |
| constexpr auto operator()(Args&&... args) && | |
| -> decltype(_call(*this, std::forward_as_tuple(std::forward<Args>(args)...))) | |
| { | |
| return _call(*this, std::forward_as_tuple(std::forward<Args>(args)...)); | |
| } | |
| template<typename... Args> | |
| constexpr auto operator()(Args&&... args) const&& | |
| -> decltype(_call(*this, std::forward_as_tuple(std::forward<Args>(args)...))) | |
| { | |
| return _call(*this, std::forward_as_tuple(std::forward<Args>(args)...)); | |
| } | |
| // Accessor | |
| [[nodiscard]] | |
| constexpr auto base() const | |
| -> F | |
| { | |
| return func; | |
| } | |
| }; | |
| // flip | |
| template<typename F> | |
| constexpr auto flip(F func) | |
| -> flip_t<F> | |
| { | |
| return flip_t<F>(std::move(func)); | |
| } | |
| template<typename F> | |
| constexpr auto flip(flip_t<F> flipped_func) | |
| -> F | |
| { | |
| return flipped_func.base(); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment