Comments (2)
I would rather suggest you make your own namespaces with the necessary overloads
This is a quick example
namespace magic_enum8 {
template <typename E>
std::u8string enum_name(E v) {
std::u8string str;
auto n = magic_enum::enum_name<E>(v);
str.reserve(n.size());
for (auto c : n)
str.append(1, c);
return str;
}
}
namespace magic_enum16 {
template <typename E>
std::u16string enum_name(E v) {
std::u16string str;
auto n = magic_enum::enum_name<E>(v);
str.reserve(n.size());
for (auto c : n)
str.append(1, c);
return str;
}
}
from magic_enum.
Thank you, I made a small adaption for Qt's QString
and QStringView
. It only supports Latin1 characters, but that shouldn't really be a limitation in practice. It's mostly constexpr
except for getting QString
s. Should work on both Qt 6 and 5 (only tested on 6 right now).
Adaptation
We have different naming conventions, but that shouldn't be an issue.
It's using is_nothrow_invocable
, enum_subtype
, subtype_v
, and enable_if_t
from magic_enum::detail
.
#include <magic_enum.hpp>
#include <QString>
#include <QStringView>
namespace qmagicenum {
namespace detail {
template <std::size_t N>
consteval QStringView fromArray(const std::array<char16_t, N> &arr)
{
return QStringView{arr.data(),
static_cast<QStringView::size_type>(N - 1)};
}
// Only the latin1 subset may be used right now, since it's easily convertible
template <std::size_t N>
consteval bool isLatin1(std::string_view maybe)
{
for (std::size_t i = 0; i < N; i++)
{
if (maybe[i] < 0x20 || maybe[i] > 0x7e)
{
return false;
}
}
return true;
}
template <typename BinaryPredicate>
inline constexpr bool eq(
QStringView a, QStringView b,
[[maybe_unused]] BinaryPredicate
&&p) noexcept(magic_enum::detail::
is_nothrow_invocable<BinaryPredicate>())
{
// Note: operator== isn't constexpr
if (a.size() != b.size())
{
return false;
}
for (QStringView::size_type i = 0; i < a.size(); i++)
{
if (!p(a[i], b[i]))
{
return false;
}
}
return true;
}
template <typename C, typename E, E V>
consteval auto enumNameStorage()
{
constexpr auto utf8 = magic_enum::enum_name<V>();
static_assert(isLatin1<utf8.size()>(utf8),
"Can't convert non-latin1 UTF8 to UTF16");
std::array<C, utf8.size() + 1> storage;
for (std::size_t i = 0; i < utf8.size(); i++)
{
storage[i] = static_cast<C>(utf8[i]);
}
storage[utf8.size()] = 0;
return storage;
}
template <typename E, E V>
inline constexpr auto ENUM_NAME_STORAGE = enumNameStorage<char16_t, E, V>();
template <typename E, magic_enum::detail::enum_subtype S, std::size_t... I>
consteval auto namesStorage(std::index_sequence<I...> /*unused*/)
{
return std::array<QStringView, sizeof...(I)>{{detail::fromArray(
ENUM_NAME_STORAGE<E, magic_enum::enum_values<E, S>()[I]>)...}};
}
template <typename E, magic_enum::detail::enum_subtype S =
magic_enum::detail::subtype_v<E>>
inline constexpr auto NAMES_STORAGE = namesStorage<E, S>(
std::make_index_sequence<magic_enum::enum_count<E, S>()>{});
} // namespace detail
/// @brief Get the name of an enum value
///
/// This version is much lighter on the compile times and is not restricted to the enum_range limitation.
///
/// @tparam V The enum value
/// @returns The name as a string view
template <auto V>
[[nodiscard]] consteval magic_enum::detail::enable_if_t<decltype(V),
QStringView>
enumName() noexcept
{
return QStringView{
detail::fromArray(detail::ENUM_NAME_STORAGE<decltype(V), V>)};
}
/// @brief Get the name of an enum value
///
/// @param value The enum value
/// @returns The name as a string view. If @a value does not have name or the
/// value is out of range an empty string is returned.
template <typename E,
magic_enum::detail::enum_subtype S = magic_enum::detail::subtype_v<E>>
[[nodiscard]] constexpr magic_enum::detail::enable_if_t<E, QStringView>
enumName(E value) noexcept
{
using D = std::decay_t<E>;
if (const auto i = magic_enum::enum_index<D, S>(value))
{
return detail::NAMES_STORAGE<D, S>[*i];
}
return {};
}
/// @brief Get the name of an enum value
///
/// This version is much lighter on the compile times and is not restricted to
/// the enum_range limitation.
///
/// @tparam V The enum value
/// @returns The name as a string. The returned string is static.
template <auto V>
[[nodiscard]] inline magic_enum::detail::enable_if_t<decltype(V), QString>
enumNameString() noexcept
{
constexpr auto view = enumName<V>();
return QString(QStringPrivate(nullptr, const_cast<char16_t *>(view.utf16()),
view.size()));
}
/// @brief Get the name of an enum value
///
/// This version is much lighter on the compile times and is not restricted to
/// the enum_range limitation.
///
/// @tparam V The enum value
/// @returns The name as a string. If @a value does not have name or the
/// value is out of range an empty string is returned.
/// The returned string is static.
template <typename E,
magic_enum::detail::enum_subtype S = magic_enum::detail::subtype_v<E>>
[[nodiscard]] inline magic_enum::detail::enable_if_t<E, QString> enumNameString(
E value) noexcept
{
using D = std::decay_t<E>;
auto view = enumName<D, S>(value);
return QString(QStringPrivate(nullptr, const_cast<char16_t *>(view.utf16()),
view.size()));
}
/// @brief Gets the enum value from a name
///
/// @tparam E The enum type to parse the @a name as
/// @param name The name of the enum value to parse
/// @param p A predicate to compare characters of a string
/// (defaults to std::equal_to)
/// @returns A `std::optional` of the parsed value. If no value was parsed,
/// `std::nullopt` is returned.
template <typename E,
magic_enum::detail::enum_subtype S = magic_enum::detail::subtype_v<E>,
typename BinaryPredicate = std::equal_to<>>
[[nodiscard]] constexpr magic_enum::detail::enable_if_t<
E, std::optional<std::decay_t<E>>, BinaryPredicate>
enumCast(QStringView name,
[[maybe_unused]] BinaryPredicate p =
{}) noexcept(magic_enum::detail::
is_nothrow_invocable<BinaryPredicate>())
{
using D = std::decay_t<E>;
if constexpr (magic_enum::enum_count<D, S>() == 0)
{
static_cast<void>(name);
return std::nullopt; // Empty enum.
}
for (std::size_t i = 0; i < magic_enum::enum_count<D, S>(); i++)
{
if (detail::eq(name, detail::NAMES_STORAGE<D, S>[i], p))
{
return magic_enum::enum_value<D, S>(i);
}
}
return std::nullopt; // Invalid value or out of range.
}
/// @brief Constructs a name from the @a flags
///
/// @param flags The combined flags to construct the name from
/// @param sep A separator between each flag (defaults to u'|')
/// @returns A string containing all names separated by @a sep. If any flag in
/// @a flags is out of rage or does not have a name, an empty string
/// is returned.
template <typename E>
[[nodiscard]] inline magic_enum::detail::enable_if_t<E, QString> enumFlagsName(
E flags, char16_t sep = u'|')
{
using D = std::decay_t<E>;
using U = std::underlying_type_t<D>;
constexpr auto S = magic_enum::detail::enum_subtype::flags; // NOLINT
QString name;
auto checkValue = U{0};
for (std::size_t i = 0; i < magic_enum::enum_count<D, S>(); ++i)
{
const auto v = static_cast<U>(magic_enum::enum_value<D, S>(i));
if ((static_cast<U>(flags) & v) != 0)
{
const auto n = detail::NAMES_STORAGE<D, S>[i];
if (!n.empty())
{
checkValue |= v;
if (!name.isEmpty())
{
name.append(sep);
}
name.append(n);
}
else
{
return {}; // Value out of range.
}
}
}
if (checkValue != 0 && checkValue == static_cast<U>(flags))
{
return name;
}
return {}; // Invalid value or out of range.
}
} // namespace qmagicenum
from magic_enum.
Related Issues (20)
- Incorrect reading enum HOT 2
- Is magic_enum supported on WindRiver VxWorks 7 SR 0640 LLVM/Clang 9.0.1 HOT 4
- enum_contains occur error when number excceed 127 HOT 2
- Cannot use `std::to_underlying` in `enum_for_each` if the value is declared via auto deduced type HOT 2
- did something happen to magic_enum::enum_for_each ? HOT 2
- Add test for module build HOT 1
- enum literals with values > 127 HOT 1
- error: declaration of ‘parent’ shadows a member of ‘magic_enum::containers::bitset<T>::reference_impl<magic_enum::containers::bitset<T>*>’ [-Werror=shadow] HOT 2
- [Feature request] add support for something like std::in_range for eums HOT 1
- magic_enum::enum_name Fails on large enums HOT 1
- Support for C++11 HOT 1
- example.cpp does not work unless i customize names HOT 1
- test_containers.cpp: error: > value computed is not used [-Werror=unused-value] HOT 3
- Construct bitset from string_view HOT 1
- Question about dead case filling part of calculate_cases function
- Is magic_enum supported on nvc++? HOT 1
- Tag v0.9.6 appears to be misplaced HOT 2
- Releasing the same Version multiple times changes Hash, breaks VCPKG HOT 7
- Pollutes /usr/local/include install directory with too many headers
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from magic_enum.