Skip to content

Commit

Permalink
add string_to_enum example
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaraslaut committed Aug 3, 2024
1 parent a09d304 commit 57cfe8d
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 17 deletions.
1 change: 1 addition & 0 deletions .github/DockerClang
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ RUN wget https://apt.llvm.org/llvm.sh
RUN chmod +x llvm.sh
RUN ./llvm.sh 19
RUN git clone -b p2996 https://github.com/bloomberg/clang-p2996.git
RUN cd /clang-p2996 && git reset HEAD~1 --hard
RUN cmake -S /clang-p2996/llvm \
-B build \
-G Ninja \
Expand Down
18 changes: 16 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
> Collection of static reflection usage examples
- [Enum to string](https://github.com/Yaraslaut/form#enum-to-string)
- [String to enum](https://github.com/Yaraslaut/form#string-to-enum)
- [Variant type to string](https://github.com/Yaraslaut/form#variant-type-to-string)
- [Padding check at compile time](https://github.com/Yaraslaut/form#padding-check-at-compile-time)
- [Create variant of all types inside the namespace](https://github.com/Yaraslaut/form#create-variant-of-all-types-inside-the-namespace)
Expand Down Expand Up @@ -53,6 +54,21 @@ void EnumToString() {
}
```


## String to enum
Transform string directly to enum

``` c++

enum class Color { red, green, blue };

void EnumToString() {
auto color = form::string_to_enum<Color>("red");
}

```
## Padding check at compile time
Calculate padding at compile time and enforce zero padding via concepts
Expand Down Expand Up @@ -88,7 +104,6 @@ void PaddingCheck() {
```

## Create variant of all types inside the namespace

``` c++
Expand All @@ -99,7 +114,6 @@ struct ClearHistoryAndReset {};
using list_variant = [:form::util::create_variant(^list):];
```

## Variant type to string
``` c++
Expand Down
46 changes: 38 additions & 8 deletions include/form/form.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,30 @@

namespace form {

namespace detail {
using namespace form;

template <typename Inner>
constexpr Inner string_to_enum(std::string_view value) {
Inner result{};

constexpr auto enum_type = []<typename Check>(this auto self, Check) {
if constexpr (std::is_enum_v<Check>) {
return ^Check;
} else {
return self(typename Check::value_type{});
}
}(Inner{});

[:util::expand(std::meta::enumerators_of(enum_type)):] >> [&]<auto e> {
if (value == util::name_of(e)) {
result = [:e:];
}
};
return result;
}
} // namespace detail

template <typename E> constexpr std::string variant_type_to_string(E value) {
std::string out = "";
[:util::expand(template_arguments_of(^E)):] >> [&]<auto e> {
Expand Down Expand Up @@ -38,6 +62,18 @@ constexpr std::string enum_to_string(E value, auto transformation) {
return transformation(enum_to_string(value));
}

template <typename E>
requires std::is_enum_v<E>
constexpr std::optional<E> string_to_enum(std::string_view value) {
return detail::string_to_enum<std::optional<E>>(value);
}

template <typename E>
requires std::is_enum_v<E>
constexpr E string_to_enum_no_check(std::string_view value) {
return detail::string_to_enum<E>(value);
}

template <typename T> bool compare(T const &lhs, T const &rhs) {
bool result = true;
if constexpr (std::is_arithmetic_v<T>)
Expand Down Expand Up @@ -79,8 +115,9 @@ template <auto refl> void run_tests() {
std::invoke_result_t<typename[:type_of(mem):]>, bool>) {
if ([:mem:]())
std::format_to(std::back_inserter(out), "{}", "\N{FIRE}");
else
else {
std::format_to(std::back_inserter(out), "{}", "\N{PILE OF POO}");
}
} else {
[:mem:]();
std::format_to(std::back_inserter(out), "{}", "\N{FOUR LEAF CLOVER}");
Expand All @@ -95,13 +132,6 @@ template <auto refl> void run_tests() {
}
}

template <typename T> constexpr void print_members() {
std::println("Members of: {}", util::name_of(^T));
[:util::expand(nonstatic_data_members_of(^T)):] >> [&]<auto mem> {
std::println("{}", util::name_of(mem));
};
}

template <typename S> consteval std::size_t get_padding() {

std::size_t pointer{offset_of(nonstatic_data_members_of(^S)[0]).bytes};
Expand Down
7 changes: 7 additions & 0 deletions include/form/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,11 @@ std::string_view get_before(std::string_view str, std::string_view delim) {
return str.substr(0, pos);
}

template <typename T> constexpr void print_members() {
std::println("Members of: {}", util::name_of(^T));
[:util::expand(nonstatic_data_members_of(^T)):] >> [&]<auto mem> {
std::println("{}", util::name_of(mem));
};
}

} // namespace form::util
3 changes: 2 additions & 1 deletion src/test.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "test.h"

int main() {
form::run_tests<^form::tests>();
form::run_tests<^form::examples>();
form::run_tests<^form::tests>();
return 0;
}
21 changes: 15 additions & 6 deletions src/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ namespace log {

template <class... Args>
inline void println(std::format_string<Args...> fmt, Args &&...args) {
#if 0
std::println(fmt, std::forward<Args>(args)...);
#endif
}

} // namespace log
Expand Down Expand Up @@ -169,7 +171,7 @@ struct ConfigEntries {
// ConfigEntry<StrongType, documentation::Dummy> strong_entry;
};

namespace detail {
namespace helper {

template <typename T, typename Tag = decltype([] {})> struct CreateUniqueT;

Expand All @@ -182,7 +184,7 @@ template <typename T> constexpr auto CreateClass() {
}
// clang-format on

} // namespace detail
} // namespace helper

namespace form_same_as {
template <typename T> int foo(T) { return -1; }
Expand All @@ -204,14 +206,12 @@ void testZ() {
deserialize(z);
}

void testPrintMembers() { form::print_members<Z>(); }

void testCreateClass() {
using hidden_type = [:detail::CreateClass<detail::CreateUniqueT<int>>():];
using hidden_type = [:helper::CreateClass<helper::CreateUniqueT<int>>():];

constexpr hidden_type value{};
constexpr auto refl_of_value = ^value;
form::print_members<[:type_of(refl_of_value):]>();
// util::print_members<[:type_of(refl_of_value):]>();
}

void testAA() {
Expand Down Expand Up @@ -406,6 +406,15 @@ bool EnumToStringWithTransform() {
return res;
}

bool StringToEnum() {
bool res = true;
res &= form::string_to_enum<Color>("red").value() == Color::red;
res &= form::string_to_enum<Color>("green").value() == Color::green;
res &= form::string_to_enum<Color>("blue").value() == Color::blue;
res &= form::string_to_enum_no_check<Color>("asdf") == Color::red;
return res;
}

void PaddingCheck() {

foo(struct_with_padding{});
Expand Down

0 comments on commit 57cfe8d

Please sign in to comment.