#ifndef RFL_INTERNAL_HASFIELDS_HPP_ #define RFL_INTERNAL_HASFIELDS_HPP_ #include #include #include "../Tuple.hpp" //#include "all_fields.hpp" #include "is_field.hpp" #include "is_flatten_field.hpp" #include "ptr_tuple_t.hpp" #include "is_named_tuple.hpp" namespace rfl { namespace internal { template constexpr bool all_fields_or_flatten() { const auto is_true_for_one = [](std::integral_constant) -> bool { using T = std::remove_cvref_t>; if constexpr (is_flatten_field_v) { return all_fields_or_flatten< ptr_tuple_t::Type>>(); } else { return is_field_v; } }; return [&](std::integer_sequence) { return (true && ... && is_true_for_one(std::integral_constant{})); } (std::make_integer_sequence>()); } template constexpr bool some_fields_or_flatten() { const auto is_true_for_one = [](std::integral_constant) -> bool { using T = std::remove_cvref_t>; if constexpr (is_flatten_field_v) { return some_fields_or_flatten< ptr_tuple_t::Type>>(); } else { return is_field_v; } }; return [&](std::integer_sequence) { return (false || ... || is_true_for_one(std::integral_constant{})); } (std::make_integer_sequence>()); } template constexpr bool has_fields() { if constexpr (is_named_tuple_v) { return true; } else { using TupleType = ptr_tuple_t; if constexpr (some_fields_or_flatten()) { static_assert( all_fields_or_flatten(), "If some of your fields are annotated using rfl::Field<...>, " "then you must annotate all of your fields. " "Also, you cannot combine annotated and " "unannotated fields using rfl::Flatten<...>."); return true; } else { return false; } } } } // namespace internal } // namespace rfl #endif