class Foo {
enum Color { kRed, kGreen, kBlue };
static constexpr const char* const kColorStr[] = { "Red", "Green", "Blue" };
};
constexpr const char* const Foo::kColorStr[];
static constexpr auto kColorStr = make_array("Red"sv, "Green"sv, "Blue"sv);
//decltype(kColorStr) == std::array<string_view, 3>
//Assumes E starts from 0 and is contiguous
template <typename E>
std::optional<E> enum_to_str(string_view s, carray_view<string_view> tags) {
for(int i = 0; i < int(tags.size()); ++i) {
if(s == tags[i]) {
return E(i);
}
}
return {};
}
assert(enum_to_str<Foo::Color>("Red", Foo::kColorStr) == Foo::Red);
template <typename... Args>
constexpr std::array<string_view,sizeof...(Args)> string_view::make_literal_array(Args... args) {
return std::array<string_view,sizeof...(Args)>(string_view(args, sizeof(args)-1)...);
}
class Foo {
enum Color { kRed, kGreen, kBlue };
static constexpr auto kColorStr = string_view::make_literal_array("Red", "Green", "Blue");
};
constexpr decltype(Foo::kColorStr) Foo::kColorStr;
I found this looking for the same problem.
There is just a minor bug with your implementation of make_literal_array :
Args should be passed as forwarding reference (is this the official term?) else the char[] arrays decays into char*
during expansion of the parameter pack, and sizeof(args) will become sizeof(char*) which
may more often than not produce unexpected results.
template <size_t N> constexpr string_view sv(const char (&literal)[N]) { return string_view(literal, N - 1); }constexpr auto colors = sva("Red", "Green", "Blue");
template <size_t... N> constexpr std::array<string_view, sizeof...(N)> sva( const char (&... literals)[N]) { return {{sv(literals)...}}; }