weh
This commit is contained in:
parent
bd402f57f5
commit
3ea546fe08
166 changed files with 18360 additions and 18199 deletions
|
@ -40,12 +40,14 @@ namespace rfl::internal {
|
|||
constexpr auto index =
|
||||
find_index<Field::name_, typename NamedTupleType::Fields>();
|
||||
static_assert(
|
||||
std::is_same<typename std::tuple_element<
|
||||
index, typename NamedTupleType::Fields>::type::Type,
|
||||
typename Field::Type>(),
|
||||
std::is_same<
|
||||
typename std::tuple_element<
|
||||
index, typename NamedTupleType::Fields>::type::Type,
|
||||
typename Field::Type>(),
|
||||
"If two fields have the same name, "
|
||||
"their type must be the same as "
|
||||
"well.");
|
||||
"well."
|
||||
);
|
||||
return Getter<NamedTupleType>::template get<index>(_tup);
|
||||
}
|
||||
|
||||
|
@ -69,12 +71,14 @@ namespace rfl::internal {
|
|||
constexpr auto index =
|
||||
find_index<Field::name_, typename NamedTupleType::Fields>();
|
||||
static_assert(
|
||||
std::is_same<typename std::tuple_element<
|
||||
index, typename NamedTupleType::Fields>::type::Type,
|
||||
typename Field::Type>(),
|
||||
std::is_same<
|
||||
typename std::tuple_element<
|
||||
index, typename NamedTupleType::Fields>::type::Type,
|
||||
typename Field::Type>(),
|
||||
"If two fields have the same name, "
|
||||
"their type must be the same as "
|
||||
"well.");
|
||||
"well."
|
||||
);
|
||||
return Getter<NamedTupleType>::template get_const<index>(_tup);
|
||||
}
|
||||
};
|
||||
|
@ -118,7 +122,8 @@ namespace rfl::internal {
|
|||
/// Retrieves the indicated value from the tuple.
|
||||
template <int _index>
|
||||
static inline const auto& get_const(
|
||||
const std::variant<NamedTupleTypes...>& _tup) {
|
||||
const std::variant<NamedTupleTypes...>& _tup
|
||||
) {
|
||||
const auto apply = [](const auto& _tup) -> const auto& {
|
||||
using NamedTupleType = std::remove_cvref_t<decltype(_tup)>;
|
||||
return Getter<NamedTupleType>::template get_const<_index>(_tup);
|
||||
|
@ -129,7 +134,8 @@ namespace rfl::internal {
|
|||
/// Gets a field by name.
|
||||
template <StringLiteral _field_name>
|
||||
static inline const auto& get_const(
|
||||
const std::variant<NamedTupleTypes...>& _tup) {
|
||||
const std::variant<NamedTupleTypes...>& _tup
|
||||
) {
|
||||
const auto apply = [](const auto& _t) -> const auto& {
|
||||
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
||||
return Getter<NamedTupleType>::template get_const<_field_name>(_t);
|
||||
|
@ -140,7 +146,8 @@ namespace rfl::internal {
|
|||
/// Gets a field by the field type.
|
||||
template <class Field>
|
||||
static inline const auto& get_const(
|
||||
const std::variant<NamedTupleTypes...>& _tup) {
|
||||
const std::variant<NamedTupleTypes...>& _tup
|
||||
) {
|
||||
const auto apply = [](const auto& _t) -> const auto& {
|
||||
using NamedTupleType = std::remove_cvref_t<decltype(_t)>;
|
||||
return Getter<NamedTupleType>::template get_const<Field>(_t);
|
||||
|
|
|
@ -39,27 +39,31 @@ namespace rfl::internal {
|
|||
template <class U, bool _skip_s, bool _skip_d>
|
||||
Skip(Skip<U, _skip_s, _skip_d>&& _other) : value_(_other.get()) {}
|
||||
|
||||
template <class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||
true>
|
||||
Skip(const U& _value) : value_(_value) {}
|
||||
|
||||
template <class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||
true>
|
||||
Skip(U&& _value) noexcept : value_(std::forward<U>(_value)) {}
|
||||
|
||||
template <class U,
|
||||
bool _skip_s,
|
||||
bool _skip_d,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U,
|
||||
bool _skip_s,
|
||||
bool _skip_d,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||
true>
|
||||
Skip(const Skip<U, _skip_s, _skip_d>& _skip) : value_(_skip.value()) {}
|
||||
|
||||
/// Assigns the underlying object to its default value.
|
||||
template <class U = Type,
|
||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U = Type,
|
||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||
type = true>
|
||||
Skip(const Default& _default) : value_(Type()) {}
|
||||
|
||||
~Skip() = default;
|
||||
|
@ -89,18 +93,20 @@ namespace rfl::internal {
|
|||
}
|
||||
|
||||
/// Assigns the underlying object.
|
||||
template <class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U,
|
||||
typename std::enable_if<std::is_convertible_v<U, Type>, bool>::type =
|
||||
true>
|
||||
auto& operator=(const U& _value) {
|
||||
value_ = _value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// Assigns the underlying object to its default value.
|
||||
template <class U = Type,
|
||||
typename std::enable_if<std::is_default_constructible_v<U>,
|
||||
bool>::type = true>
|
||||
template <
|
||||
class U = Type,
|
||||
typename std::enable_if<std::is_default_constructible_v<U>, bool>::
|
||||
type = true>
|
||||
auto& operator=(const Default& _default) {
|
||||
value_ = Type();
|
||||
return *this;
|
||||
|
|
|
@ -34,15 +34,19 @@ namespace rfl {
|
|||
};
|
||||
|
||||
template <size_t N1, size_t N2>
|
||||
constexpr inline bool operator==(const StringLiteral<N1>& _first,
|
||||
const StringLiteral<N2>& _second) {
|
||||
constexpr inline bool operator==(
|
||||
const StringLiteral<N1>& _first,
|
||||
const StringLiteral<N2>& _second
|
||||
) {
|
||||
if constexpr (N1 != N2) { return false; }
|
||||
return _first.string_view() == _second.string_view();
|
||||
}
|
||||
|
||||
template <size_t N1, size_t N2>
|
||||
constexpr inline bool operator!=(const StringLiteral<N1>& _first,
|
||||
const StringLiteral<N2>& _second) {
|
||||
constexpr inline bool operator!=(
|
||||
const StringLiteral<N1>& _first,
|
||||
const StringLiteral<N2>& _second
|
||||
) {
|
||||
return !(_first == _second);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,8 @@ namespace rfl {
|
|||
struct VisitTree {
|
||||
/// Evaluates a visitor pattern using a tree-like structure.
|
||||
template <int _begin, int _end, class Visitor, class... Args>
|
||||
static inline auto visit(const auto& _v,
|
||||
const int _i,
|
||||
const Args&... _args) {
|
||||
static inline auto
|
||||
visit(const auto& _v, const int _i, const Args&... _args) {
|
||||
static_assert(_end > _begin, "_end needs to be greater than _begin.");
|
||||
if constexpr (_end - _begin == 1) {
|
||||
return _v.template visit<_begin>(_args...);
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -13,8 +13,10 @@ namespace rfl {
|
|||
namespace internal {
|
||||
|
||||
template <class FieldNames, class... Fields>
|
||||
auto copy_flattened_tuple_to_named_tuple(const auto& _flattened_tuple,
|
||||
Fields&&... _fields) {
|
||||
auto copy_flattened_tuple_to_named_tuple(
|
||||
const auto& _flattened_tuple,
|
||||
Fields&&... _fields
|
||||
) {
|
||||
constexpr auto size =
|
||||
std::tuple_size_v<std::remove_cvref_t<decltype(_flattened_tuple)>>;
|
||||
constexpr auto i = sizeof...(_fields);
|
||||
|
@ -22,11 +24,13 @@ namespace rfl {
|
|||
return make_named_tuple(std::move(_fields)...);
|
||||
} else {
|
||||
const auto name_literal = FieldNames::template name_of<i>();
|
||||
auto new_field = rfl::make_field<
|
||||
auto new_field = rfl::make_field<
|
||||
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
||||
std::get<i>(_flattened_tuple));
|
||||
std::get<i>(_flattened_tuple)
|
||||
);
|
||||
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
||||
_flattened_tuple, std::move(_fields)..., std::move(new_field));
|
||||
_flattened_tuple, std::move(_fields)..., std::move(new_field)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,14 +11,17 @@ namespace rfl {
|
|||
struct define_literal;
|
||||
|
||||
/// General case
|
||||
template <StringLiteral... _content1,
|
||||
StringLiteral... _content2,
|
||||
class... Tail>
|
||||
struct define_literal<Literal<_content1...>,
|
||||
Literal<_content2...>,
|
||||
Tail...> {
|
||||
using type = typename define_literal<Literal<_content1..., _content2...>,
|
||||
Tail...>::type;
|
||||
template <
|
||||
StringLiteral... _content1,
|
||||
StringLiteral... _content2,
|
||||
class... Tail>
|
||||
struct define_literal<
|
||||
Literal<_content1...>,
|
||||
Literal<_content2...>,
|
||||
Tail...> {
|
||||
using type = typename define_literal<
|
||||
Literal<_content1..., _content2...>,
|
||||
Tail...>::type;
|
||||
};
|
||||
|
||||
/// Special case - only a single literal is left
|
||||
|
|
|
@ -20,20 +20,22 @@ namespace rfl {
|
|||
/// Recursive case - first type is NamedTuple, second type is field.
|
||||
template <class Head, class... TupContent, class... Tail>
|
||||
struct define_named_tuple<NamedTuple<TupContent...>, Head, Tail...> {
|
||||
using type = typename define_named_tuple<NamedTuple<TupContent..., Head>,
|
||||
Tail...>::type;
|
||||
using type = typename define_named_tuple<
|
||||
NamedTuple<TupContent..., Head>,
|
||||
Tail...>::type;
|
||||
};
|
||||
|
||||
/// Allows you to combine several named tuples and/or additional fields.
|
||||
/// Recursive case - first type is NamedTuple, second type is also
|
||||
/// NamedTuple.
|
||||
template <class... TupContent, class... TupContent2, class... Tail>
|
||||
struct define_named_tuple<NamedTuple<TupContent...>,
|
||||
NamedTuple<TupContent2...>,
|
||||
Tail...> {
|
||||
using type =
|
||||
typename define_named_tuple<NamedTuple<TupContent..., TupContent2...>,
|
||||
Tail...>::type;
|
||||
struct define_named_tuple<
|
||||
NamedTuple<TupContent...>,
|
||||
NamedTuple<TupContent2...>,
|
||||
Tail...> {
|
||||
using type = typename define_named_tuple<
|
||||
NamedTuple<TupContent..., TupContent2...>,
|
||||
Tail...>::type;
|
||||
};
|
||||
|
||||
/// Allows you to combine several named tuples and/or additional fields.
|
||||
|
|
|
@ -12,14 +12,16 @@ namespace rfl {
|
|||
struct define_tagged_union;
|
||||
|
||||
/// Recursive case - both tagged union.
|
||||
template <StringLiteral _discriminator,
|
||||
class... NamedTupleTypes1,
|
||||
class... NamedTupleTypes2,
|
||||
class... Tail>
|
||||
struct define_tagged_union<_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
||||
Tail...> {
|
||||
template <
|
||||
StringLiteral _discriminator,
|
||||
class... NamedTupleTypes1,
|
||||
class... NamedTupleTypes2,
|
||||
class... Tail>
|
||||
struct define_tagged_union<
|
||||
_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes1...>,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes2...>,
|
||||
Tail...> {
|
||||
using type = typename define_tagged_union<
|
||||
_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes1..., NamedTupleTypes2...>,
|
||||
|
@ -27,27 +29,31 @@ namespace rfl {
|
|||
};
|
||||
|
||||
/// Recursive case - tagged union plus named tuple.
|
||||
template <StringLiteral _discriminator,
|
||||
class... NamedTupleTypes,
|
||||
class... FieldTypes,
|
||||
class... Tail>
|
||||
struct define_tagged_union<_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
||||
NamedTuple<FieldTypes...>,
|
||||
Tail...> {
|
||||
using type =
|
||||
typename define_tagged_union<_discriminator,
|
||||
TaggedUnion<_discriminator,
|
||||
NamedTupleTypes...,
|
||||
NamedTuple<FieldTypes...>>,
|
||||
Tail...>::type;
|
||||
template <
|
||||
StringLiteral _discriminator,
|
||||
class... NamedTupleTypes,
|
||||
class... FieldTypes,
|
||||
class... Tail>
|
||||
struct define_tagged_union<
|
||||
_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTupleTypes...>,
|
||||
NamedTuple<FieldTypes...>,
|
||||
Tail...> {
|
||||
using type = typename define_tagged_union<
|
||||
_discriminator,
|
||||
TaggedUnion<
|
||||
_discriminator,
|
||||
NamedTupleTypes...,
|
||||
NamedTuple<FieldTypes...>>,
|
||||
Tail...>::type;
|
||||
};
|
||||
|
||||
/// Recursive case - named tuple.
|
||||
template <StringLiteral _discriminator, class... FieldTypes, class... Tail>
|
||||
struct define_tagged_union<_discriminator,
|
||||
NamedTuple<FieldTypes...>,
|
||||
Tail...> {
|
||||
struct define_tagged_union<
|
||||
_discriminator,
|
||||
NamedTuple<FieldTypes...>,
|
||||
Tail...> {
|
||||
using type = typename define_tagged_union<
|
||||
_discriminator,
|
||||
TaggedUnion<_discriminator, NamedTuple<FieldTypes...>>,
|
||||
|
|
|
@ -12,11 +12,13 @@ namespace rfl {
|
|||
|
||||
/// Recursive case - both variants.
|
||||
template <class... Vars1, class... Vars2, class... Tail>
|
||||
struct define_variant<std::variant<Vars1...>,
|
||||
std::variant<Vars2...>,
|
||||
Tail...> {
|
||||
using type = typename define_variant<std::variant<Vars1..., Vars2...>,
|
||||
Tail...>::type;
|
||||
struct define_variant<
|
||||
std::variant<Vars1...>,
|
||||
std::variant<Vars2...>,
|
||||
Tail...> {
|
||||
using type =
|
||||
typename define_variant<std::variant<Vars1..., Vars2...>, Tail...>::
|
||||
type;
|
||||
};
|
||||
|
||||
/// Recursive case - variant plus other type.
|
||||
|
|
|
@ -29,63 +29,86 @@ namespace rfl {
|
|||
constexpr static std::array<EnumType, N> enums_ =
|
||||
std::array<EnumType, N> {_enums...};
|
||||
|
||||
static_assert(N == 0 || LiteralType::size() == N,
|
||||
"Size of literal and enum do not match.");
|
||||
static_assert(
|
||||
N == 0 || LiteralType::size() == N,
|
||||
"Size of literal and enum do not match."
|
||||
);
|
||||
|
||||
template <class NewLiteral, auto _new_enum>
|
||||
using AddOneType =
|
||||
std::conditional_t<N == 0,
|
||||
Names<EnumType, NewLiteral, 1, _new_enum>,
|
||||
Names<EnumType,
|
||||
define_literal_t<LiteralType, NewLiteral>,
|
||||
N + 1,
|
||||
_enums...,
|
||||
_new_enum>>;
|
||||
using AddOneType = std::conditional_t<
|
||||
N == 0,
|
||||
Names<EnumType, NewLiteral, 1, _new_enum>,
|
||||
Names<
|
||||
EnumType,
|
||||
define_literal_t<LiteralType, NewLiteral>,
|
||||
N + 1,
|
||||
_enums...,
|
||||
_new_enum>>;
|
||||
};
|
||||
|
||||
template <class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
auto names_to_enumerator_named_tuple(
|
||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||
template <
|
||||
class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
auto names_to_enumerator_named_tuple(Names<
|
||||
EnumType,
|
||||
Literal<_names...>,
|
||||
N,
|
||||
_enums...>) {
|
||||
return make_named_tuple(Field<_names, EnumType> {_enums}...);
|
||||
}
|
||||
|
||||
template <class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
auto names_to_underlying_enumerator_named_tuple(
|
||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||
template <
|
||||
class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
auto names_to_underlying_enumerator_named_tuple(Names<
|
||||
EnumType,
|
||||
Literal<_names...>,
|
||||
N,
|
||||
_enums...>) {
|
||||
return make_named_tuple(
|
||||
Field<_names, std::underlying_type_t<EnumType>> {
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enums)}...);
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
||||
}...
|
||||
);
|
||||
}
|
||||
|
||||
template <class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
template <
|
||||
class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
constexpr std::array<std::pair<std::string_view, EnumType>, N>
|
||||
names_to_enumerator_array(
|
||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||
return {std::make_pair(LiteralHelper<_names>::field_.string_view(),
|
||||
_enums)...};
|
||||
names_to_enumerator_array(Names<
|
||||
EnumType,
|
||||
Literal<_names...>,
|
||||
N,
|
||||
_enums...>) {
|
||||
return {std::make_pair(
|
||||
LiteralHelper<_names>::field_.string_view(), _enums
|
||||
)...};
|
||||
}
|
||||
|
||||
template <class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
template <
|
||||
class EnumType,
|
||||
size_t N,
|
||||
StringLiteral... _names,
|
||||
auto... _enums>
|
||||
constexpr std::array<
|
||||
std::pair<std::string_view, std::underlying_type_t<EnumType>>,
|
||||
N>
|
||||
names_to_underlying_enumerator_array(
|
||||
Names<EnumType, Literal<_names...>, N, _enums...>) {
|
||||
names_to_underlying_enumerator_array(Names<
|
||||
EnumType,
|
||||
Literal<_names...>,
|
||||
N,
|
||||
_enums...>) {
|
||||
return {std::make_pair(
|
||||
LiteralHelper<_names>::field_.string_view(),
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enums))...};
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enums)
|
||||
)...};
|
||||
}
|
||||
|
||||
} // namespace enums
|
||||
|
|
|
@ -43,7 +43,8 @@ namespace rfl {
|
|||
static_assert(
|
||||
names_.size != 0,
|
||||
"No enum could be identified. Please choose enum values "
|
||||
"between 0 to 127 or for flag enums choose 1,2,4,8,16,...");
|
||||
"between 0 to 127 or for flag enums choose 1,2,4,8,16,..."
|
||||
);
|
||||
if constexpr (is_flag_enum_) {
|
||||
return string_to_flag_enum(_str);
|
||||
} else {
|
||||
|
@ -55,15 +56,16 @@ namespace rfl {
|
|||
/// Iterates through the enum bit by bit and matches it against the
|
||||
/// flags.
|
||||
static std::string flag_enum_to_string(const EnumType _e) {
|
||||
using T = std::underlying_type_t<EnumType>;
|
||||
auto val = static_cast<T>(_e);
|
||||
int i = 0;
|
||||
using T = std::underlying_type_t<EnumType>;
|
||||
auto val = static_cast<T>(_e);
|
||||
int i = 0;
|
||||
std::vector<std::string> flags;
|
||||
while (val != 0) {
|
||||
const auto bit = val & static_cast<T>(1);
|
||||
if (bit == 1) {
|
||||
auto str = enum_to_single_string(
|
||||
static_cast<EnumType>(static_cast<T>(1) << i));
|
||||
static_cast<EnumType>(static_cast<T>(1) << i)
|
||||
);
|
||||
flags.emplace_back(std::move(str));
|
||||
}
|
||||
++i;
|
||||
|
@ -80,14 +82,16 @@ namespace rfl {
|
|||
for (size_t i = 0; i < names_.size; ++i) {
|
||||
if (names_.enums_[i] == _enum) {
|
||||
return NamesLiteral::from_value(
|
||||
static_cast<typename NamesLiteral::ValueType>(i))
|
||||
static_cast<typename NamesLiteral::ValueType>(i)
|
||||
)
|
||||
.transform(to_str)
|
||||
.value();
|
||||
}
|
||||
}
|
||||
|
||||
return std::to_string(
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enum));
|
||||
static_cast<std::underlying_type_t<EnumType>>(_enum)
|
||||
);
|
||||
}
|
||||
|
||||
/// Finds the enum matching the literal.
|
||||
|
@ -111,11 +115,11 @@ namespace rfl {
|
|||
|
||||
/// Only relevant if this is a flag enum - combines the different
|
||||
/// matches using |.
|
||||
static Result<EnumType> string_to_flag_enum(
|
||||
const std::string& _str) noexcept {
|
||||
static Result<EnumType> string_to_flag_enum(const std::string& _str
|
||||
) noexcept {
|
||||
using T = std::underlying_type_t<EnumType>;
|
||||
const auto split = strings::split(_str, "|");
|
||||
auto res = static_cast<T>(0);
|
||||
auto res = static_cast<T>(0);
|
||||
for (const auto& s : split) {
|
||||
const auto r = single_string_to_enum(s);
|
||||
if (r) {
|
||||
|
|
|
@ -63,7 +63,8 @@ namespace rfl {
|
|||
static_assert(
|
||||
false,
|
||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||
"or MSVC or use rfl::Literal.");
|
||||
"or MSVC or use rfl::Literal."
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -105,11 +106,12 @@ namespace rfl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class EnumType,
|
||||
class NamesType,
|
||||
auto _max,
|
||||
bool _is_flag,
|
||||
int _i>
|
||||
template <
|
||||
class EnumType,
|
||||
class NamesType,
|
||||
auto _max,
|
||||
bool _is_flag,
|
||||
int _i>
|
||||
consteval auto get_enum_names_impl() {
|
||||
using T = std::underlying_type_t<EnumType>;
|
||||
|
||||
|
@ -121,8 +123,8 @@ namespace rfl {
|
|||
if constexpr (j == _max) {
|
||||
return NamesType {};
|
||||
} else {
|
||||
return get_enum_names_impl<EnumType, NamesType, _max, _is_flag,
|
||||
_i + 1>();
|
||||
return get_enum_names_impl<
|
||||
EnumType, NamesType, _max, _is_flag, _i + 1>();
|
||||
}
|
||||
} else {
|
||||
using NewNames = typename NamesType::template AddOneType<
|
||||
|
@ -131,8 +133,8 @@ namespace rfl {
|
|||
if constexpr (j == _max) {
|
||||
return NewNames {};
|
||||
} else {
|
||||
return get_enum_names_impl<EnumType, NewNames, _max, _is_flag,
|
||||
_i + 1>();
|
||||
return get_enum_names_impl<
|
||||
EnumType, NewNames, _max, _is_flag, _i + 1>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -142,10 +144,13 @@ namespace rfl {
|
|||
static_assert(
|
||||
is_scoped_enum<EnumType>,
|
||||
"You must use scoped enums (using class or struct) for the "
|
||||
"parsing to work!");
|
||||
"parsing to work!"
|
||||
);
|
||||
|
||||
static_assert(std::is_integral_v<std::underlying_type_t<EnumType>>,
|
||||
"The underlying type of any Enum must be integral!");
|
||||
static_assert(
|
||||
std::is_integral_v<std::underlying_type_t<EnumType>>,
|
||||
"The underlying type of any Enum must be integral!"
|
||||
);
|
||||
|
||||
constexpr auto max =
|
||||
get_max<std::underlying_type_t<EnumType>, _is_flag>();
|
||||
|
|
|
@ -35,9 +35,10 @@ namespace rfl {
|
|||
|
||||
/// For variants - in this case the FieldType returned by all options must
|
||||
/// be the same.
|
||||
template <StringLiteral _field_name,
|
||||
class FirstAlternativeType,
|
||||
class... OtherAlternativeTypes>
|
||||
template <
|
||||
StringLiteral _field_name,
|
||||
class FirstAlternativeType,
|
||||
class... OtherAlternativeTypes>
|
||||
struct FieldType<
|
||||
_field_name,
|
||||
std::variant<FirstAlternativeType, OtherAlternativeTypes...>> {
|
||||
|
@ -51,15 +52,17 @@ namespace rfl {
|
|||
};
|
||||
|
||||
/// For tagged union - just defers to the variant.
|
||||
template <StringLiteral _field_name,
|
||||
StringLiteral _discriminator_name,
|
||||
class... VarTypes>
|
||||
struct FieldType<_field_name,
|
||||
TaggedUnion<_discriminator_name, VarTypes...>> {
|
||||
template <
|
||||
StringLiteral _field_name,
|
||||
StringLiteral _discriminator_name,
|
||||
class... VarTypes>
|
||||
struct FieldType<
|
||||
_field_name,
|
||||
TaggedUnion<_discriminator_name, VarTypes...>> {
|
||||
using Type = typename FieldType<
|
||||
_field_name,
|
||||
typename TaggedUnion<_discriminator_name,
|
||||
VarTypes...>::VariantType>::Type;
|
||||
typename TaggedUnion<_discriminator_name, VarTypes...>::VariantType>::
|
||||
Type;
|
||||
};
|
||||
|
||||
} // namespace internal
|
||||
|
|
|
@ -10,9 +10,8 @@ namespace rfl {
|
|||
namespace internal {
|
||||
|
||||
template <class T>
|
||||
using flattened_ptr_tuple_t =
|
||||
typename std::invoke_result<decltype(to_flattened_ptr_tuple<T>),
|
||||
T>::type;
|
||||
using flattened_ptr_tuple_t = typename std::
|
||||
invoke_result<decltype(to_flattened_ptr_tuple<T>), T>::type;
|
||||
|
||||
} // namespace internal
|
||||
} // namespace rfl
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace rfl {
|
|||
|
||||
template <class T>
|
||||
struct wrapper {
|
||||
const T value;
|
||||
const T value;
|
||||
static const wrapper<T> report_if_you_see_a_link_error_with_this_object;
|
||||
};
|
||||
|
||||
|
|
|
@ -64,14 +64,15 @@ namespace rfl::internal {
|
|||
static_assert(
|
||||
false,
|
||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||
"or MSVC or switch to the rfl::Field-syntax.");
|
||||
"or MSVC or switch to the rfl::Field-syntax."
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T, auto ptr>
|
||||
consteval auto get_field_name_str_lit() {
|
||||
constexpr auto name = get_field_name_str_view<T, ptr>();
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
constexpr auto name = get_field_name_str_view<T, ptr>();
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
||||
};
|
||||
return to_str_lit(std::make_index_sequence<name.size()> {});
|
||||
|
@ -99,8 +100,10 @@ namespace rfl::internal {
|
|||
}
|
||||
|
||||
template <StringLiteral... _names1, StringLiteral... _names2>
|
||||
auto concat_two_literals(const rfl::Literal<_names1...>& _lit1,
|
||||
const rfl::Literal<_names2...>& _lit2) {
|
||||
auto concat_two_literals(
|
||||
const rfl::Literal<_names1...>& _lit1,
|
||||
const rfl::Literal<_names2...>& _lit2
|
||||
) {
|
||||
return rfl::Literal<_names1..., _names2...>::template from_value<0>();
|
||||
}
|
||||
|
||||
|
@ -135,14 +138,16 @@ namespace rfl::internal {
|
|||
#if defined(__clang__)
|
||||
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||
return concat_literals(
|
||||
get_field_name<Type, wrap(std::get<Is>(
|
||||
bind_fake_object_to_tuple<T>()))>()...);
|
||||
get_field_name<
|
||||
Type, wrap(std::get<Is>(bind_fake_object_to_tuple<T>()))>()...
|
||||
);
|
||||
};
|
||||
#else
|
||||
const auto get = []<std::size_t... Is>(std::index_sequence<Is...>) {
|
||||
return concat_literals(
|
||||
get_field_name<Type,
|
||||
std::get<Is>(bind_fake_object_to_tuple<T>())>()...);
|
||||
get_field_name<Type, std::get<Is>(bind_fake_object_to_tuple<T>())>(
|
||||
)...
|
||||
);
|
||||
};
|
||||
#endif
|
||||
return get(std::make_index_sequence<num_fields<T>>());
|
||||
|
|
|
@ -23,7 +23,8 @@ namespace rfl {
|
|||
auto type = type_name_t<typename FieldType::Type>().str();
|
||||
return get_meta_fields<NamedTupleType>(
|
||||
std::move(_already_extracted)...,
|
||||
MetaField(std::move(name), std::move(type)));
|
||||
MetaField(std::move(name), std::move(type))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -35,16 +35,19 @@ namespace rfl {
|
|||
static_assert(
|
||||
false,
|
||||
"You are using an unsupported compiler. Please use GCC, Clang "
|
||||
"or MSVC or explicitly tag your structs using 'Tag' or 'Name'.");
|
||||
"or MSVC or explicitly tag your structs using 'Tag' or 'Name'."
|
||||
);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <class T>
|
||||
consteval auto get_type_name() {
|
||||
static_assert(get_type_name_str_view<int>() == "int",
|
||||
"Expected 'int', got something else.");
|
||||
constexpr auto name = get_type_name_str_view<T>();
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
static_assert(
|
||||
get_type_name_str_view<int>() == "int",
|
||||
"Expected 'int', got something else."
|
||||
);
|
||||
constexpr auto name = get_type_name_str_view<T>();
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
return StringLiteral<sizeof...(Ns) + 1> {name[Ns]...};
|
||||
};
|
||||
return to_str_lit(std::make_index_sequence<name.size()> {});
|
||||
|
|
|
@ -57,7 +57,8 @@ namespace rfl {
|
|||
"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<...>.");
|
||||
"unannotated fields using rfl::Flatten<...>."
|
||||
);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
|
|
@ -20,11 +20,14 @@ namespace rfl {
|
|||
return move_and_flatten_field_tuple(
|
||||
std::move(_t), std::move(_args)...,
|
||||
move_and_flatten_field_tuple(
|
||||
move_to_field_tuple(std::move(std::get<i>(_t).value_))));
|
||||
move_to_field_tuple(std::move(std::get<i>(_t).value_))
|
||||
)
|
||||
);
|
||||
} else {
|
||||
return move_and_flatten_field_tuple(
|
||||
std::move(_t), std::move(_args)...,
|
||||
std::make_tuple(std::move(std::get<i>(_t))));
|
||||
std::make_tuple(std::move(std::get<i>(_t)))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,23 +29,25 @@ namespace rfl {
|
|||
std::remove_cvref_t<std::remove_pointer_t<typename Field::Type>>;
|
||||
|
||||
if constexpr (is_named_tuple_v<T>) {
|
||||
using SubPtrNamedTupleType =
|
||||
typename std::invoke_result<decltype(nt_to_ptr_named_tuple<T>),
|
||||
T>::type;
|
||||
using SubPtrNamedTupleType = typename std::invoke_result<
|
||||
decltype(nt_to_ptr_named_tuple<T>), T>::type;
|
||||
|
||||
return make_ptr_fields<PtrFieldTupleType>(
|
||||
_n, _args..., SubPtrNamedTupleType(_n).fields());
|
||||
_n, _args..., SubPtrNamedTupleType(_n).fields()
|
||||
);
|
||||
|
||||
} else if constexpr (is_flatten_field<Field>::value) {
|
||||
using SubPtrFieldTupleType =
|
||||
std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||
|
||||
return make_ptr_fields<PtrFieldTupleType>(
|
||||
_n, _args..., make_ptr_fields<SubPtrFieldTupleType>(_n));
|
||||
_n, _args..., make_ptr_fields<SubPtrFieldTupleType>(_n)
|
||||
);
|
||||
|
||||
} else {
|
||||
return make_ptr_fields<PtrFieldTupleType>(
|
||||
_n, _args..., _n.template get_field<Field::name_>());
|
||||
_n, _args..., _n.template get_field<Field::name_>()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +65,9 @@ namespace rfl {
|
|||
return move_from_ptr_fields<T>(
|
||||
_ptrs, std::move(_args)...,
|
||||
rfl::make_field<FieldType::name_>(
|
||||
std::move(*std::get<i>(_ptrs).value())));
|
||||
std::move(*std::get<i>(_ptrs).value())
|
||||
)
|
||||
);
|
||||
|
||||
} else {
|
||||
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||
|
@ -73,7 +77,8 @@ namespace rfl {
|
|||
|
||||
return move_from_ptr_fields<T>(
|
||||
_ptrs, std::move(_args)...,
|
||||
move_from_ptr_fields<U>(std::get<i>(_ptrs)));
|
||||
move_from_ptr_fields<U>(std::get<i>(_ptrs))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,8 +92,9 @@ namespace rfl {
|
|||
if constexpr (is_named_tuple_v<std::remove_cvref_t<T>>) {
|
||||
return std::move(_n);
|
||||
|
||||
} else if constexpr (std::is_same<std::remove_cvref_t<NamedTupleType>,
|
||||
RequiredType>()) {
|
||||
} else if constexpr (std::is_same<
|
||||
std::remove_cvref_t<NamedTupleType>,
|
||||
RequiredType>()) {
|
||||
auto ptr_named_tuple = nt_to_ptr_named_tuple(_n);
|
||||
|
||||
using PtrFieldTupleType = std::remove_cvref_t<ptr_field_tuple_t<T>>;
|
||||
|
@ -98,8 +104,8 @@ namespace rfl {
|
|||
return move_from_ptr_fields<T>(pointers);
|
||||
|
||||
} else {
|
||||
return move_from_named_tuple<T, RequiredType>(
|
||||
RequiredType(std::move(_n)));
|
||||
return move_from_named_tuple<T, RequiredType>(RequiredType(std::move(_n)
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,11 @@ namespace rfl {
|
|||
}
|
||||
}
|
||||
|
||||
template <class TargetTupleType,
|
||||
class PtrTupleType,
|
||||
int _j = 0,
|
||||
class... Args>
|
||||
template <
|
||||
class TargetTupleType,
|
||||
class PtrTupleType,
|
||||
int _j = 0,
|
||||
class... Args>
|
||||
auto unflatten_ptr_tuple(PtrTupleType& _t, Args... _args) {
|
||||
constexpr auto i = sizeof...(Args);
|
||||
|
||||
|
@ -52,14 +53,16 @@ namespace rfl {
|
|||
constexpr int flattened_size =
|
||||
calc_flattened_size<SubTargetTupleType>();
|
||||
|
||||
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType,
|
||||
_j + flattened_size>(
|
||||
return unflatten_ptr_tuple<
|
||||
TargetTupleType, PtrTupleType, _j + flattened_size>(
|
||||
_t, _args...,
|
||||
unflatten_ptr_tuple<SubTargetTupleType, PtrTupleType, _j>(_t));
|
||||
unflatten_ptr_tuple<SubTargetTupleType, PtrTupleType, _j>(_t)
|
||||
);
|
||||
|
||||
} else {
|
||||
return unflatten_ptr_tuple<TargetTupleType, PtrTupleType, _j + 1>(
|
||||
_t, _args..., std::get<_j>(_t));
|
||||
_t, _args..., std::get<_j>(_t)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -74,8 +77,9 @@ namespace rfl {
|
|||
std::tuple_element_t<i, std::remove_cvref_t<Pointers>>;
|
||||
|
||||
if constexpr (std::is_pointer_v<FieldType>) {
|
||||
return move_from_pointers<T>(_ptrs, std::move(_args)...,
|
||||
std::move(*std::get<i>(_ptrs)));
|
||||
return move_from_pointers<T>(
|
||||
_ptrs, std::move(_args)..., std::move(*std::get<i>(_ptrs))
|
||||
);
|
||||
|
||||
} else {
|
||||
using PtrTupleType = ptr_tuple_t<std::remove_cvref_t<T>>;
|
||||
|
@ -85,7 +89,8 @@ namespace rfl {
|
|||
|
||||
return move_from_pointers<T>(
|
||||
_ptrs, std::move(_args)...,
|
||||
move_from_pointers<U>(std::get<i>(_ptrs)));
|
||||
move_from_pointers<U>(std::get<i>(_ptrs))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,16 +24,16 @@ namespace rfl {
|
|||
using FieldType = typename std::tuple_element<i, Fields>::type;
|
||||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||
return nt_to_ptr_named_tuple(
|
||||
_nt, _a...,
|
||||
Field<FieldType::name_, T*>(&std::get<i>(_nt.values())));
|
||||
_nt, _a..., Field<FieldType::name_, T*>(&std::get<i>(_nt.values()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// Generates a named tuple that contains pointers to the original values in
|
||||
/// the struct from a named tuple.
|
||||
template <class NamedTupleType, class... AlreadyExtracted>
|
||||
auto nt_to_ptr_named_tuple(const NamedTupleType& _nt,
|
||||
AlreadyExtracted... _a) {
|
||||
auto
|
||||
nt_to_ptr_named_tuple(const NamedTupleType& _nt, AlreadyExtracted... _a) {
|
||||
using Fields = typename NamedTupleType::Fields;
|
||||
|
||||
constexpr auto i = sizeof...(AlreadyExtracted);
|
||||
|
@ -46,7 +46,8 @@ namespace rfl {
|
|||
using T = std::remove_cvref_t<typename FieldType::Type>;
|
||||
return nt_to_ptr_named_tuple(
|
||||
_nt, _a...,
|
||||
Field<FieldType::name_, const T*>(&std::get<i>(_nt.values())));
|
||||
Field<FieldType::name_, const T*>(&std::get<i>(_nt.values()))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,11 +53,7 @@ namespace rfl {
|
|||
struct any_empty_base {
|
||||
any_empty_base(std::size_t);
|
||||
template <class Base>
|
||||
requires(std::is_empty_v<std::remove_cvref_t<Base>> &&
|
||||
std::is_base_of_v<std::remove_cvref_t<Base>,
|
||||
std::remove_cv_t<Derived>> &&
|
||||
!std::is_same_v<std::remove_cvref_t<Base>,
|
||||
std::remove_cv_t<Derived>>)
|
||||
requires(std::is_empty_v<std::remove_cvref_t<Base>> && std::is_base_of_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>> && !std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
|
||||
constexpr operator Base&() const noexcept;
|
||||
};
|
||||
|
||||
|
@ -65,10 +61,7 @@ namespace rfl {
|
|||
struct any_base {
|
||||
any_base(std::size_t);
|
||||
template <class Base>
|
||||
requires(std::is_base_of_v<std::remove_cvref_t<Base>,
|
||||
std::remove_cv_t<Derived>> &&
|
||||
!std::is_same_v<std::remove_cvref_t<Base>,
|
||||
std::remove_cv_t<Derived>>)
|
||||
requires(std::is_base_of_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>> && !std::is_same_v<std::remove_cvref_t<Base>, std::remove_cv_t<Derived>>)
|
||||
constexpr operator Base&() const noexcept;
|
||||
};
|
||||
|
||||
|
@ -89,12 +82,13 @@ namespace rfl {
|
|||
|
||||
template <std::size_t l, std::size_t nested, std::size_t r>
|
||||
static consteval bool constructible_with_nested() {
|
||||
return []<std::size_t... i, std::size_t... j, std::size_t... k>(
|
||||
std::index_sequence<i...>, std::index_sequence<j...>,
|
||||
std::index_sequence<k...>) {
|
||||
return requires { T {any(i)..., {any(j)...}, any(k)...}; };
|
||||
}(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
|
||||
std::make_index_sequence<r>());
|
||||
return
|
||||
[]<std::size_t... i, std::size_t... j,
|
||||
std::
|
||||
size_t... k>(std::index_sequence<i...>, std::index_sequence<j...>, std::index_sequence<k...>) {
|
||||
return requires { T {any(i)..., {any(j)...}, any(k)...}; };
|
||||
}(std::make_index_sequence<l>(), std::make_index_sequence<nested>(),
|
||||
std::make_index_sequence<r>());
|
||||
}
|
||||
|
||||
template <std::size_t n = 0>
|
||||
|
@ -112,8 +106,8 @@ namespace rfl {
|
|||
if constexpr (size < 1) {
|
||||
return 1;
|
||||
} else if constexpr (constructible_with_nested<index, size, rest>() &&
|
||||
!constructible_with_nested<index, size,
|
||||
rest + 1>()) {
|
||||
!constructible_with_nested<index, size, rest + 1>(
|
||||
)) {
|
||||
return size;
|
||||
} else {
|
||||
return get_nested_array_size<index, size - 1, rest + 1>();
|
||||
|
@ -123,17 +117,20 @@ namespace rfl {
|
|||
template <std::size_t max_args, std::size_t index = 0>
|
||||
static consteval std::size_t find_the_sole_non_empty_base_index() {
|
||||
static_assert(index < max_args);
|
||||
constexpr auto check = []<std::size_t... l, std::size_t... r>(
|
||||
std::index_sequence<l...>,
|
||||
std::index_sequence<r...>) {
|
||||
return requires {
|
||||
T {any_empty_base<T>(l)..., any_base<T>(0),
|
||||
any_empty_base<T>(r)...};
|
||||
};
|
||||
};
|
||||
constexpr auto check =
|
||||
[]<std::size_t... l,
|
||||
std::
|
||||
size_t... r>(std::index_sequence<l...>, std::index_sequence<r...>) {
|
||||
return requires {
|
||||
T {any_empty_base<T>(l)..., any_base<T>(0),
|
||||
any_empty_base<T>(r)...};
|
||||
};
|
||||
};
|
||||
|
||||
if constexpr (check(std::make_index_sequence<index>(),
|
||||
std::make_index_sequence<max_args - index - 1>())) {
|
||||
if constexpr (check(
|
||||
std::make_index_sequence<index>(),
|
||||
std::make_index_sequence<max_args - index - 1>()
|
||||
)) {
|
||||
return index;
|
||||
} else {
|
||||
return find_the_sole_non_empty_base_index<max_args, index + 1>();
|
||||
|
@ -154,10 +151,13 @@ namespace rfl {
|
|||
template <std::size_t n, std::size_t max_arg_num>
|
||||
static consteval bool has_n_base_param() {
|
||||
constexpr auto right_len = max_arg_num >= n ? max_arg_num - n : 0;
|
||||
return []<std::size_t... l, std::size_t... r>(
|
||||
std::index_sequence<l...>, std::index_sequence<r...>) {
|
||||
return requires { T {any_base<T>(l)..., any(r)...}; };
|
||||
}(std::make_index_sequence<n>(), std::make_index_sequence<right_len>());
|
||||
return
|
||||
[]<std::size_t... l,
|
||||
std::
|
||||
size_t... r>(std::index_sequence<l...>, std::index_sequence<r...>) {
|
||||
return requires { T {any_base<T>(l)..., any(r)...}; };
|
||||
}(std::make_index_sequence<n>(),
|
||||
std::make_index_sequence<right_len>());
|
||||
}
|
||||
|
||||
template <std::size_t max_arg_num, std::size_t index = 0>
|
||||
|
|
|
@ -15,8 +15,8 @@ namespace rfl::internal {
|
|||
struct Processed<StructType, Processors<Ps...>> {
|
||||
using NamedTupleType = named_tuple_t<StructType>;
|
||||
using type = typename std::invoke_result<
|
||||
decltype(Processors<Ps...>::template process<StructType,
|
||||
NamedTupleType>),
|
||||
decltype(Processors<
|
||||
Ps...>::template process<StructType, NamedTupleType>),
|
||||
NamedTupleType>::type;
|
||||
};
|
||||
|
||||
|
|
|
@ -14,28 +14,32 @@ namespace rfl {
|
|||
|
||||
/// Recursively builds a new NamedTuple type from the FieldTypes, leaving
|
||||
/// out the field signified by _name.
|
||||
template <class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType,
|
||||
int _i>
|
||||
template <
|
||||
class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType,
|
||||
int _i>
|
||||
struct remove_single_field;
|
||||
|
||||
/// Special case - _i == 0
|
||||
template <class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType>
|
||||
struct remove_single_field<_OldNamedTupleType,
|
||||
_name,
|
||||
_NewNamedTupleType,
|
||||
0> {
|
||||
template <
|
||||
class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType>
|
||||
struct remove_single_field<
|
||||
_OldNamedTupleType,
|
||||
_name,
|
||||
_NewNamedTupleType,
|
||||
0> {
|
||||
using type = _NewNamedTupleType;
|
||||
};
|
||||
|
||||
/// General case.
|
||||
template <class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType,
|
||||
int _i>
|
||||
template <
|
||||
class _OldNamedTupleType,
|
||||
StringLiteral _name,
|
||||
class _NewNamedTupleType,
|
||||
int _i>
|
||||
struct remove_single_field {
|
||||
using OldNamedTupleType = std::remove_cvref_t<_OldNamedTupleType>;
|
||||
|
||||
|
@ -51,17 +55,19 @@ namespace rfl {
|
|||
_NewNamedTupleType,
|
||||
define_named_tuple_t<_NewNamedTupleType, FieldType>>;
|
||||
|
||||
using type = typename remove_single_field<OldNamedTupleType,
|
||||
_name,
|
||||
NewNamedTupleType,
|
||||
_i - 1>::type;
|
||||
using type = typename remove_single_field<
|
||||
OldNamedTupleType,
|
||||
_name,
|
||||
NewNamedTupleType,
|
||||
_i - 1>::type;
|
||||
};
|
||||
|
||||
/// Recursively removes all of the fields signified by _head and _tail from
|
||||
/// the NamedTupleType.
|
||||
template <class _NamedTupleType,
|
||||
StringLiteral _head,
|
||||
StringLiteral... _tail>
|
||||
template <
|
||||
class _NamedTupleType,
|
||||
StringLiteral _head,
|
||||
StringLiteral... _tail>
|
||||
struct remove_fields;
|
||||
|
||||
/// Special case - only head is left.
|
||||
|
@ -72,26 +78,29 @@ namespace rfl {
|
|||
constexpr static int num_fields =
|
||||
std::tuple_size_v<typename NamedTupleType::Fields>;
|
||||
|
||||
using type = typename remove_single_field<NamedTupleType,
|
||||
_head,
|
||||
NamedTuple<>,
|
||||
num_fields>::type;
|
||||
using type = typename remove_single_field<
|
||||
NamedTupleType,
|
||||
_head,
|
||||
NamedTuple<>,
|
||||
num_fields>::type;
|
||||
};
|
||||
|
||||
/// General case.
|
||||
template <class _NamedTupleType,
|
||||
StringLiteral _head,
|
||||
StringLiteral... _tail>
|
||||
template <
|
||||
class _NamedTupleType,
|
||||
StringLiteral _head,
|
||||
StringLiteral... _tail>
|
||||
struct remove_fields {
|
||||
using NamedTupleType = std::remove_cvref_t<_NamedTupleType>;
|
||||
|
||||
constexpr static int num_fields =
|
||||
std::tuple_size_v<typename NamedTupleType::Fields>;
|
||||
|
||||
using NewNamedTupleType = typename remove_single_field<NamedTupleType,
|
||||
_head,
|
||||
NamedTuple<>,
|
||||
num_fields>::type;
|
||||
using NewNamedTupleType = typename remove_single_field<
|
||||
NamedTupleType,
|
||||
_head,
|
||||
NamedTuple<>,
|
||||
num_fields>::type;
|
||||
|
||||
using type = typename remove_fields<NewNamedTupleType, _tail...>::type;
|
||||
};
|
||||
|
|
|
@ -12,11 +12,11 @@ namespace rfl {
|
|||
|
||||
template <StringLiteral _name>
|
||||
consteval auto remove_namespaces() {
|
||||
constexpr auto name = _name.string_view();
|
||||
constexpr size_t pos = name.find_last_of(":");
|
||||
constexpr auto name = _name.string_view();
|
||||
constexpr size_t pos = name.find_last_of(":");
|
||||
if constexpr (pos == std::string_view::npos) { return _name; }
|
||||
constexpr auto substr = name.substr(pos + 1);
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
constexpr auto substr = name.substr(pos + 1);
|
||||
const auto to_str_lit = [&]<auto... Ns>(std::index_sequence<Ns...>) {
|
||||
return StringLiteral<sizeof...(Ns) + 1> {substr[Ns]...};
|
||||
};
|
||||
return to_str_lit(std::make_index_sequence<substr.size()> {});
|
||||
|
|
|
@ -9,8 +9,10 @@ namespace rfl {
|
|||
namespace strings {
|
||||
|
||||
/// Joins a string using the delimiter
|
||||
inline std::string join(const std::string& _delimiter,
|
||||
const std::vector<std::string>& _strings) {
|
||||
inline std::string join(
|
||||
const std::string& _delimiter,
|
||||
const std::vector<std::string>& _strings
|
||||
) {
|
||||
if (_strings.size() == 0) { return ""; }
|
||||
auto res = _strings[0];
|
||||
for (size_t i = 1; i < _strings.size(); ++i) {
|
||||
|
|
|
@ -8,9 +8,11 @@ namespace rfl {
|
|||
namespace internal {
|
||||
namespace strings {
|
||||
|
||||
inline std::string replace_all(const std::string& _str,
|
||||
const std::string& _from,
|
||||
const std::string& _to) {
|
||||
inline std::string replace_all(
|
||||
const std::string& _str,
|
||||
const std::string& _from,
|
||||
const std::string& _to
|
||||
) {
|
||||
auto str = _str;
|
||||
|
||||
size_t pos = 0;
|
||||
|
|
|
@ -9,10 +9,10 @@ namespace rfl {
|
|||
namespace strings {
|
||||
|
||||
/// Splits a string alongside the delimiter
|
||||
inline std::vector<std::string> split(const std::string& _str,
|
||||
const std::string& _delimiter) {
|
||||
auto str = _str;
|
||||
size_t pos = 0;
|
||||
inline std::vector<std::string>
|
||||
split(const std::string& _str, const std::string& _delimiter) {
|
||||
auto str = _str;
|
||||
size_t pos = 0;
|
||||
std::vector<std::string> result;
|
||||
while ((pos = str.find(_delimiter)) != std::string::npos) {
|
||||
result.emplace_back(str.substr(0, pos));
|
||||
|
|
|
@ -9,9 +9,8 @@
|
|||
namespace rfl::internal {
|
||||
|
||||
template <internal::StringLiteral _discriminator, class T>
|
||||
using tag_t =
|
||||
typename std::invoke_result<decltype(make_tag<_discriminator, T>),
|
||||
T>::type;
|
||||
using tag_t = typename std::
|
||||
invoke_result<decltype(make_tag<_discriminator, T>), T>::type;
|
||||
|
||||
} // namespace rfl::internal
|
||||
|
||||
|
|
|
@ -23,11 +23,13 @@ namespace rfl {
|
|||
if constexpr (is_flatten_field_v<T>) {
|
||||
return flatten_ptr_tuple(
|
||||
std::forward<PtrTuple>(_t), std::forward<Args>(_args)...,
|
||||
flatten_ptr_tuple(to_ptr_tuple(std::get<i>(_t)->get())));
|
||||
flatten_ptr_tuple(to_ptr_tuple(std::get<i>(_t)->get()))
|
||||
);
|
||||
} else {
|
||||
return flatten_ptr_tuple(std::forward<PtrTuple>(_t),
|
||||
std::forward<Args>(_args)...,
|
||||
std::make_tuple(std::get<i>(_t)));
|
||||
return flatten_ptr_tuple(
|
||||
std::forward<PtrTuple>(_t), std::forward<Args>(_args)...,
|
||||
std::make_tuple(std::get<i>(_t))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,11 +29,14 @@ namespace rfl {
|
|||
using T = std::tuple_element_t<i, std::remove_cvref_t<PtrFieldTuple>>;
|
||||
if constexpr (internal::is_flatten_field<T>::value) {
|
||||
auto subtuple = internal::to_ptr_field_tuple(*std::get<i>(_t).get());
|
||||
return flatten_ptr_field_tuple(_t, std::forward<Args>(_args)...,
|
||||
flatten_ptr_field_tuple(subtuple));
|
||||
return flatten_ptr_field_tuple(
|
||||
_t, std::forward<Args>(_args)...,
|
||||
flatten_ptr_field_tuple(subtuple)
|
||||
);
|
||||
} else {
|
||||
return flatten_ptr_field_tuple(_t, std::forward<Args>(_args)...,
|
||||
std::make_tuple(std::get<i>(_t)));
|
||||
return flatten_ptr_field_tuple(
|
||||
_t, std::forward<Args>(_args)..., std::make_tuple(std::get<i>(_t))
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +74,8 @@ namespace rfl {
|
|||
using FieldNames = rfl::field_names_t<T>;
|
||||
auto flattened_ptr_tuple = to_flattened_ptr_tuple(_t);
|
||||
return copy_flattened_tuple_to_named_tuple<FieldNames>(
|
||||
flattened_ptr_tuple);
|
||||
flattened_ptr_tuple
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,8 @@ namespace rfl::internal {
|
|||
constexpr size_t n = StdArrayType<Type>::size;
|
||||
const auto fct = [&]<std::size_t... _i>(std::index_sequence<_i...>) {
|
||||
return to_std_array_t<Type>({to_std_array(
|
||||
std::forward<typename StdArrayType<Type>::ValueType>(_t[_i]))...});
|
||||
std::forward<typename StdArrayType<Type>::ValueType>(_t[_i])
|
||||
)...});
|
||||
};
|
||||
return fct(std::make_index_sequence<n>());
|
||||
} else {
|
||||
|
|
|
@ -16,10 +16,11 @@ namespace rfl::internal {
|
|||
}
|
||||
|
||||
/// Transforms the field name from snake case to camel case.
|
||||
template <internal::StringLiteral _name,
|
||||
bool _capitalize,
|
||||
size_t _i = 0,
|
||||
char... chars>
|
||||
template <
|
||||
internal::StringLiteral _name,
|
||||
bool _capitalize,
|
||||
size_t _i = 0,
|
||||
char... chars>
|
||||
consteval auto transform_snake_case() {
|
||||
if constexpr (_i == _name.arr_.size()) {
|
||||
return StringLiteral<sizeof...(chars) + 1>(chars...);
|
||||
|
@ -28,11 +29,11 @@ namespace rfl::internal {
|
|||
} else if constexpr (_name.arr_[_i] == '\0') {
|
||||
return transform_snake_case<_name, false, _name.arr_.size(), chars...>();
|
||||
} else if constexpr (_capitalize) {
|
||||
return transform_snake_case<_name, false, _i + 1, chars...,
|
||||
to_upper<_name.arr_[_i]>()>();
|
||||
return transform_snake_case<
|
||||
_name, false, _i + 1, chars..., to_upper<_name.arr_[_i]>()>();
|
||||
} else {
|
||||
return transform_snake_case<_name, false, _i + 1, chars...,
|
||||
_name.arr_[_i]>();
|
||||
return transform_snake_case<
|
||||
_name, false, _i + 1, chars..., _name.arr_[_i]>();
|
||||
}
|
||||
}
|
||||
} // namespace rfl::internal
|
||||
|
|
|
@ -28,14 +28,17 @@ namespace rfl {
|
|||
constexpr auto n_skip = std::tuple_size_v<
|
||||
std::remove_cvref_t<flattened_ptr_tuple_t<typename Type::Type>>>;
|
||||
return wrap_in_fields<FieldNames, j + n_skip>(
|
||||
std::move(_tuple), std::move(_fields)..., std::move(value));
|
||||
std::move(_tuple), std::move(_fields)..., std::move(value)
|
||||
);
|
||||
} else {
|
||||
const auto name_literal = FieldNames::template name_of<j>();
|
||||
auto new_field = rfl::make_field<
|
||||
auto new_field = rfl::make_field<
|
||||
lit_name_v<std::remove_cvref_t<decltype(name_literal)>>>(
|
||||
std::move(value));
|
||||
std::move(value)
|
||||
);
|
||||
return wrap_in_fields<FieldNames, j + 1>(
|
||||
std::move(_tuple), std::move(_fields)..., std::move(new_field));
|
||||
std::move(_tuple), std::move(_fields)..., std::move(new_field)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue