From 6e52a6262d8d869e72dba27eed868b0d170c594f Mon Sep 17 00:00:00 2001 From: sha512sum Date: Tue, 27 Feb 2024 18:40:42 +0000 Subject: [PATCH] Add GoInterface --- include/utempl/go_interface.hpp | 78 +++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) create mode 100644 include/utempl/go_interface.hpp diff --git a/include/utempl/go_interface.hpp b/include/utempl/go_interface.hpp new file mode 100644 index 0000000..b5ca77c --- /dev/null +++ b/include/utempl/go_interface.hpp @@ -0,0 +1,78 @@ +#pragma once +#include +#include +#include + +namespace utempl { + +template +consteval auto FindField() -> std::size_t { + constexpr auto names = boost::pfr::names_as_array>(); + return std::ranges::find(names, static_cast(name)) - names.begin(); +}; + +template +inline constexpr auto Get(T&& arg) { + return boost::pfr::get()>(std::forward(arg)); +}; + +template +struct EmptyField {}; + +namespace impl { + + +template +inline constexpr auto TryGet(T&& arg) + -> decltype(boost::pfr::get()>(std::forward(arg))) + requires(FindField() < boost::pfr::tuple_size_v>) { + constexpr auto I = FindField(); + return boost::pfr::get(std::forward(arg)); +}; +template +inline constexpr auto TryGet(T&& arg) { + return EmptyField{}; +}; + + +template +inline constexpr auto Transform(Transformer&& transformer, From&& from) { + return [&](std::index_sequence){ + return To{transformer(TryGet().size() + 1>{boost::pfr::get_name().begin()}>(from))...}; + }(std::make_index_sequence>()); +}; + +} // impl + +struct DefaultFieldTransformer { + inline constexpr auto operator()(auto&& arg) -> auto&& { + return arg; + }; + inline constexpr auto operator()(auto& arg) -> auto& { + return arg; + }; + template + inline constexpr auto operator()(EmptyField arg) { + static_assert(str == "This Field Not Found"); + }; +}; + +template +struct GoInterface : Value { + inline constexpr GoInterface(Value&& value) : + Value(std::move(value)) {}; + inline constexpr GoInterface(const Value& value) : + Value(value) {}; + template + inline constexpr GoInterface(T&& value) : + Value(impl::Transform(Transformer{}, std::forward(value))) {}; + inline constexpr auto operator=(const GoInterface&) -> GoInterface& = default; + inline constexpr auto operator=(GoInterface&&) -> GoInterface& = default; + inline constexpr auto operator==(const GoInterface& other) const -> bool + requires requires {static_cast(*this) == static_cast(other);} { + return static_cast(*this) == static_cast(other); + }; +}; + +} // namespace utempl +