Skip to content

Commit

Permalink
Add a special case to from_str() for RS_ENUM[_CLASS]() types
Browse files Browse the repository at this point in the history
  • Loading branch information
CaptainCrowbar committed Jul 9, 2019
1 parent 3ffddb4 commit ba11f59
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 0 deletions.
1 change: 1 addition & 0 deletions doc/utility.html
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,7 @@ <h2 id="string-functions">String functions</h2>
<li>An empty string yields a default constructed <code>T</code></li>
<li>If <code>T</code> is <code>bool</code>, check for the strings <code>"true"</code> or <code>"false"</code>, otherwise treat as numeric</li>
<li>If <code>T</code> is a primitive integer or floating point type, call the appropriate <code>strto*()</code> function</li>
<li>If <code>T</code> is an enumeration defined with <code>RS_ENUM[_CLASS]()</code>, call its <code>str_to_enum()</code> function</li>
<li>Try a <code>static_cast</code> from <code>std::string_view</code>, <code>std::string</code>, or <code>const char*</code> to <code>T</code></li>
<li>Read a <code>T</code> from a <code>std::istringstream</code> using <code>operator&gt;&gt;</code></li>
<li>Otherwise fail</li>
Expand Down
13 changes: 13 additions & 0 deletions unicorn/utility-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,19 @@ void test_unicorn_utility_conversion_from_string() {
TEST(from_str<bool>("true"));
TEST_THROW(from_str<bool>("hello"), std::invalid_argument);

TEST_EQUAL(from_str<FooEnum>("alpha"), alpha);
TEST_EQUAL(from_str<FooEnum>("FooEnum::alpha"), alpha);
TEST_EQUAL(from_str<BarEnum>("delta"), delta);
TEST_EQUAL(from_str<BarEnum>("BarEnum::delta"), delta);
TEST_EQUAL(from_str<ZapEnum>("golf"), ZapEnum::golf);
TEST_EQUAL(from_str<ZapEnum>("ZapEnum::golf"), ZapEnum::golf);
TEST_EQUAL(from_str<ThogEnum>("golf"), ThogEnum::golf);
TEST_EQUAL(from_str<ThogEnum>("ThogEnum::golf"), ThogEnum::golf);
TEST_THROW(from_str<FooEnum>("ALPHA"), std::invalid_argument);
TEST_THROW(from_str<BarEnum>("DELTA"), std::invalid_argument);
TEST_THROW(from_str<ZapEnum>("GOLF"), std::invalid_argument);
TEST_THROW(from_str<ThogEnum>("GOLF"), std::invalid_argument);

}

namespace {
Expand Down
3 changes: 3 additions & 0 deletions unicorn/utility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1320,6 +1320,7 @@ namespace RS {
template <typename T> using StrMethodArchetype = decltype(std::declval<T>().str());
template <typename T> using AdlToStringArchetype = decltype(to_string(std::declval<T>()));
template <typename T> using StdToStringArchetype = decltype(std::to_string(std::declval<T>()));
template <typename T> using StrToEnumArchetype = decltype(str_to_enum(std::string_view(), std::declval<T&>()));

template <typename T> struct IsByteArray: public std::false_type {};
template <typename A> struct IsByteArray<std::vector<unsigned char, A>>: public std::true_type {};
Expand Down Expand Up @@ -1408,6 +1409,8 @@ namespace RS {
return false;
t = rc;
return true;
} else if constexpr (Meta::is_detected<StrToEnumArchetype, T>) {
return str_to_enum(view, t);
} else if constexpr (std::is_constructible_v<T, std::string_view>) {
t = static_cast<T>(view);
return true;
Expand Down
1 change: 1 addition & 0 deletions unicorn/utility.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ that matches the type:
* An empty string yields a default constructed `T`
* If `T` is `bool`, check for the strings `"true"` or `"false"`, otherwise treat as numeric
* If `T` is a primitive integer or floating point type, call the appropriate `strto*()` function
* If `T` is an enumeration defined with `RS_ENUM[_CLASS]()`, call its `str_to_enum()` function
* Try a `static_cast` from `std::string_view`, `std::string`, or `const char*` to `T`
* Read a `T` from a `std::istringstream` using `operator>>`
* Otherwise fail
Expand Down

0 comments on commit ba11f59

Please sign in to comment.