#define constexpr_toupper(text) detail::toupper<text>()
namespace detail {
inline static constexpr char toupper(char c) {
return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c;
}
template <size_t size>
struct CopyUppercase {
inline constexpr Copy(const char (&text)[size]) {
std::copy_n(text, size, _data.begin());
std::transform(_data.begin(), _data.end(), _data.begin(), [](char c) {
return toupper(c);
});
}
std::array<char, size> _data;
};
template <CopyUppercase text>
inline static constexpr const char* toupper() {
return text._data.data();
}
} // namespace detail
// C++14
#define constexpr_toupper(text) detail::toupper(detail::Split<text>)
namespace detail {
template <size_t size>
struct Copy {
inline constexpr Copy(const char (&text)[size]) {
std::copy_n(text, size, _data.begin());
}
std::array<char, size> _data;
};
template <char... c>
struct Join {
inline static constexpr char value[] = { c... };
};
template <Copy copy>
inline static constexpr auto Split = ([]<size_t... i>(std::index_sequence<i...>) {
return Join<copy._data[i]...>();
})(std::make_index_sequence<copy._data.size()>());
inline static constexpr char toupper(char c) {
return (c >= 'a' && c <= 'z') ? (c - 'a' + 'A') : c;
}
template <char... c>
inline static constexpr std::string_view toupper(Join<c...>) {
return std::string_view(Join<toupper(c)...>::value);
}
} // namespace detail