#ifndef RFL_INTERNAL_GETTER_HPP_ #define RFL_INTERNAL_GETTER_HPP_ #include #include #include "StringLiteral.hpp" #include "find_index.hpp" namespace rfl::internal { // ---------------------------------------------------------------------------- template struct Getter; // ---------------------------------------------------------------------------- /// Default case - anything that cannot be explicitly matched. template struct Getter { public: /// Retrieves the indicated value from the tuple. template static inline auto& get(NamedTupleType& _tup) { return std::get<_index>(_tup.values()); } /// Gets a field by name. template static inline auto& get(NamedTupleType& _tup) { constexpr auto index = find_index<_field_name, typename NamedTupleType::Fields>(); return Getter::template get(_tup); } /// Gets a field by the field type. template static inline auto& get(NamedTupleType& _tup) { constexpr auto index = find_index(); static_assert( std::is_same< typename std::tuple_element::type::Type, typename Field::Type>(), "If two fields have the same name, " "their type must be the same as " "well." ); return Getter::template get(_tup); } /// Retrieves the indicated value from the tuple. template static inline const auto& get_const(const NamedTupleType& _tup) { return std::get<_index>(_tup.values()); } /// Gets a field by name. template static inline const auto& get_const(const NamedTupleType& _tup) { constexpr auto index = find_index<_field_name, typename NamedTupleType::Fields>(); return Getter::template get_const(_tup); } /// Gets a field by the field type. template static inline const auto& get_const(const NamedTupleType& _tup) { constexpr auto index = find_index(); static_assert( std::is_same< typename std::tuple_element::type::Type, typename Field::Type>(), "If two fields have the same name, " "their type must be the same as " "well." ); return Getter::template get_const(_tup); } }; // ---------------------------------------------------------------------------- /// For handling std::variant. template struct Getter> { public: /// Retrieves the indicated value from the tuple. template static inline auto& get(std::variant& _tup) { const auto apply = [](auto& _t) -> auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get<_index>(_t); }; return std::visit(apply, _tup); } /// Gets a field by name. template static inline auto& get(std::variant& _tup) { const auto apply = [](auto& _t) -> auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get<_field_name>(_t); }; return std::visit(apply, _tup); } /// Gets a field by the field type. template static inline auto& get(std::variant& _tup) { const auto apply = [](auto& _t) -> auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get(_t); }; return std::visit(apply, _tup); } /// Retrieves the indicated value from the tuple. template static inline const auto& get_const(const std::variant& _tup) { const auto apply = [](const auto& _tup) -> const auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get_const<_index>(_tup); }; return std::visit(apply, _tup); } /// Gets a field by name. template static inline const auto& get_const(const std::variant& _tup) { const auto apply = [](const auto& _t) -> const auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get_const<_field_name>(_t); }; return std::visit(apply, _tup); } /// Gets a field by the field type. template static inline const auto& get_const(const std::variant& _tup) { const auto apply = [](const auto& _t) -> const auto& { using NamedTupleType = std::remove_cvref_t; return Getter::template get_const(_t); }; return std::visit(apply, _tup); } }; // ---------------------------------------------------------------------------- } // namespace rfl::internal #endif