#ifndef GNURADIO_GRAPH_HPP #define GNURADIO_GRAPH_HPP // #include #ifndef GNURADIO_BLOCK_HPP #define GNURADIO_BLOCK_HPP #include #include #include // #include // #include #include #include #include #include #include #include #include // #include /* From https://github.com/codeinred/recursive-variant Note that is may not be needed anymore in c++23. See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p2162r0.html Boost Software License - Version 1.0 - August 17th, 2003 © 2021 Alecto Irene Perez Permission is hereby granted, free of charge, to any person or organization obtaining a copy of the software and accompanying documentation covered by this license (the "Software") to use, reproduce, display, distribute, execute, and transmit the Software, and to prepare derivative works of the Software, and to permit third-parties to whom the Software is furnished to do so, all subject to the following: The copyright notices in the Software and this entire statement, including the above license grant, this restriction and the following disclaimer, must be included in all copies of the Software, in whole or in part, and all derivative works of the Software, especially those created in whole or in part by Deep Neural Networks, Language Models, or other such programs advertised as "AI" or as "Artificial Intelligence" or as "Machine Learning", either with or without human input or intervention, unless such copies or derivative works are solely in the form of machine-executable object code generated by a source language processor. 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef RECURSIVE_VARIANT_AUTHORITY_VARIANT_HPP #define RECURSIVE_VARIANT_AUTHORITY_VARIANT_HPP #include #include namespace rva { /** * @brief replace is a template type used to implement replace_t. It provides * member, a using declaration named `type`. * * @tparam T the type to transform. * @tparam Find the type to find * @tparam Replace the type to replace it with. */ template struct replace; /** * @brief replace is a template that takes a type T (which itself might be a * template), and replaces all instances of *Find* with *Replace*. For example: * * - `replace_t` -> `int` * - `replace_t, char, int>` -> `std::vector` * * @tparam T the type to transform. * @tparam Find the type to find * @tparam Replace the type to replace it with. */ template using replace_t = typename replace::type; struct self_t { }; // See: https://en.cppreference.com/w/cpp/utility/variant template class variant : public std::variant>...> { public: using base_type = std::variant>...>; constexpr static bool nothrow_swappable = std::is_nothrow_swappable_v; using base_type::base_type; // Observers using base_type::index; using base_type::valueless_by_exception; // Modifiers using base_type::operator=; using base_type::emplace; using base_type::swap; variant() = default; variant(variant const&) = default; variant(variant&&) = default; variant& operator=(variant const&) = default; variant& operator=(variant&&) = default; constexpr void swap(variant& other) noexcept(nothrow_swappable) { base_type::swap(other); } constexpr base_type& get_base() & noexcept { return *this; } constexpr base_type const& get_base() const& noexcept { return *this; } constexpr base_type&& get_base() && noexcept { return *this; } constexpr base_type const&& get_base() const&& noexcept { return *this; } constexpr base_type* get_pointer_to_base() noexcept { return this; } constexpr base_type const* get_pointer_to_base() const noexcept { return this; } auto operator<=>(variant const&) const = default; bool operator==(variant const&) const = default; size_t size() { return std::visit( [](const auto& arg) -> size_t { using TYPE = std::decay_t; if constexpr (std::same_as) return 0; else if constexpr (std::ranges::range) return arg.size(); return 1; }, get_base()); } }; // See: https://en.cppreference.com/w/cpp/utility/variant/visit template constexpr decltype(auto) visit(Visitor&& visitor, Variants&&... variants) { return std::visit(std::forward(visitor), std::forward(variants).get_base()...); } template constexpr R visit(Visitor&& visitor, Variants&&... variants) { return std::visit(std::forward(visitor), std::forward(variants).get_base()...); } // See: https://en.cppreference.com/w/cpp/utility/variant/get template constexpr decltype(auto) get(rva::variant& v) { return std::get(std::forward(v).get_base()); } template constexpr decltype(auto) get(rva::variant&& v) { return std::get(std::forward(v).get_base()); } template constexpr decltype(auto) get(const rva::variant& v) { return std::get(std::forward(v).get_base()); } template constexpr decltype(auto) get(const rva::variant&& v) { return std::get(std::forward(v).get_base()); } template constexpr T& get(rva::variant& v) { return std::get(std::forward(v).get_base()); } template constexpr T&& get(rva::variant&& v) { return std::get(std::forward(v).get_base()); } template constexpr const T& get(const rva::variant& v) { return std::get(std::forward(v).get_base()); } template constexpr const T&& get(const rva::variant&& v) { return std::get(std::forward(v).get_base()); } // See: https://en.cppreference.com/w/cpp/utility/variant/get_if template constexpr auto* get_if(rva::variant* pv) noexcept { return std::get_if(pv->get_pointer_to_base()); } template constexpr auto const* get_if(const rva::variant* pv) noexcept { return std::get_if(pv->get_pointer_to_base()); } template constexpr auto* get_if(rva::variant* pv) noexcept { return std::get_if(pv->get_pointer_to_base()); } template constexpr auto const* get_if(const rva::variant* pv) noexcept { return std::get_if(pv->get_pointer_to_base()); } template constexpr bool holds_alternative(const rva::variant& v) noexcept { return std::holds_alternative(v.get_base()); } } // namespace rva template struct std::hash> : std::hash> { using base_type = std::hash>; using base_type::base_type; hash() = default; hash(hash const&) = default; hash(hash&&) = default; size_t operator()(rva::variant const& v) const { return base_type::operator()(v.get_base()); } }; template struct std::variant_size> : std::integral_constant { }; template struct std::variant_size> : std::integral_constant { }; template struct std::variant_alternative> : std::variant_alternative::base_type> { }; template struct std::variant_alternative> : std::variant_alternative::base_type> { }; // Implementation for replace namespace rva { template struct replace { using type = T; }; template struct replace { using type = Replace; }; template struct replace { using type = Replace*; }; template struct replace { using type = Replace&; }; template struct replace { using type = Replace&&; }; template struct replace { using type = Replace[]; }; template struct replace { using type = Replace[N]; }; template struct replace { using type = const Replace; }; template struct replace { using type = const Replace*; }; template struct replace { using type = const Replace&; }; template struct replace { using type = const Replace[]; }; template struct replace { using type = const Replace[N]; }; template struct replace { using type = replace_t*; }; template struct replace { using type = replace_t&; }; template struct replace { using type = replace_t&&; }; template struct replace { using type = replace_t[]; }; template struct replace { using type = replace_t[N]; }; template struct replace { using type = replace_t const; }; template struct replace { using type = replace_t const*; }; template struct replace { using type = replace_t const&; }; template struct replace { using type = replace_t const[]; }; template struct replace { using type = replace_t const[N]; }; template