Add format_as for enums

This commit is contained in:
Victor Zverovich 2022-01-28 06:31:29 -08:00
parent b00a1eac75
commit 1557ab7644
2 changed files with 34 additions and 18 deletions

View File

@ -51,7 +51,7 @@
#ifdef __NVCOMPILER #ifdef __NVCOMPILER
# define FMT_NVCOMPILER_VERSION \ # define FMT_NVCOMPILER_VERSION \
(__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__) (__NVCOMPILER_MAJOR__ * 100 + __NVCOMPILER_MINOR__)
#else #else
# define FMT_NVCOMPILER_VERSION 0 # define FMT_NVCOMPILER_VERSION 0
#endif #endif
@ -336,8 +336,8 @@ FMT_BEGIN_DETAIL_NAMESPACE
// (void)var does not work on many Intel compilers. // (void)var does not work on many Intel compilers.
template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {} template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value = false) constexpr FMT_INLINE auto is_constant_evaluated(
noexcept -> bool { bool default_value = false) noexcept -> bool {
#ifdef __cpp_lib_is_constant_evaluated #ifdef __cpp_lib_is_constant_evaluated
ignore_unused(default_value); ignore_unused(default_value);
return std::is_constant_evaluated(); return std::is_constant_evaluated();
@ -443,8 +443,7 @@ template <typename Char> class basic_string_view {
/** Constructs a string reference object from a C string and a size. */ /** Constructs a string reference object from a C string and a size. */
constexpr basic_string_view(const Char* s, size_t count) noexcept constexpr basic_string_view(const Char* s, size_t count) noexcept
: data_(s), : data_(s), size_(count) {}
size_(count) {}
/** /**
\rst \rst
@ -465,13 +464,12 @@ template <typename Char> class basic_string_view {
template <typename Traits, typename Alloc> template <typename Traits, typename Alloc>
FMT_CONSTEXPR basic_string_view( FMT_CONSTEXPR basic_string_view(
const std::basic_string<Char, Traits, Alloc>& s) noexcept const std::basic_string<Char, Traits, Alloc>& s) noexcept
: data_(s.data()), : data_(s.data()), size_(s.size()) {}
size_(s.size()) {}
template <typename S, FMT_ENABLE_IF(std::is_same< template <typename S, FMT_ENABLE_IF(std::is_same<
S, detail::std_string_view<Char>>::value)> S, detail::std_string_view<Char>>::value)>
FMT_CONSTEXPR basic_string_view(S s) noexcept : data_(s.data()), FMT_CONSTEXPR basic_string_view(S s) noexcept
size_(s.size()) {} : data_(s.data()), size_(s.size()) {}
/** Returns a pointer to the string data. */ /** Returns a pointer to the string data. */
constexpr auto data() const noexcept -> const Char* { return data_; } constexpr auto data() const noexcept -> const Char* { return data_; }
@ -640,9 +638,7 @@ class basic_format_parse_context : private ErrorHandler {
/** /**
Returns an iterator past the end of the format string range being parsed. Returns an iterator past the end of the format string range being parsed.
*/ */
constexpr auto end() const noexcept -> iterator { constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
return format_str_.end();
}
/** Advances the begin iterator to ``it``. */ /** Advances the begin iterator to ``it``. */
FMT_CONSTEXPR void advance_to(iterator it) { FMT_CONSTEXPR void advance_to(iterator it) {
@ -771,10 +767,8 @@ template <typename T> class buffer {
FMT_MSC_WARNING(suppress : 26495) FMT_MSC_WARNING(suppress : 26495)
buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {} buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {}
FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
size_t cap = 0) noexcept : ptr_(p), : ptr_(p), size_(sz), capacity_(cap) {}
size_(sz),
capacity_(cap) {}
FMT_CONSTEXPR20 ~buffer() = default; FMT_CONSTEXPR20 ~buffer() = default;
buffer(buffer&&) = default; buffer(buffer&&) = default;
@ -1428,6 +1422,13 @@ template <typename Context> struct arg_mapper {
return map(static_cast<typename std::underlying_type<T>::type>(val)); return map(static_cast<typename std::underlying_type<T>::type>(val));
} }
template <typename T, typename U = decltype(format_as(T())),
FMT_ENABLE_IF(std::is_enum<T>::value&& std::is_integral<U>::value)>
FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
-> decltype(std::declval<arg_mapper>().map(U())) {
return map(format_as(val));
}
FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned { FMT_CONSTEXPR FMT_INLINE auto map(detail::byte val) -> unsigned {
return map(static_cast<unsigned char>(val)); return map(static_cast<unsigned char>(val));
} }

View File

@ -755,7 +755,16 @@ template <> struct formatter<convertible_to_pointer_formattable> {
}; };
FMT_END_NAMESPACE FMT_END_NAMESPACE
enum class test_scoped_enum {}; enum class unformattable_scoped_enum {};
namespace test {
enum class formattable_scoped_enum {};
auto format_as(formattable_scoped_enum) -> int { return 42; }
struct convertible_to_enum {
operator formattable_scoped_enum() const { return {}; }
};
} // namespace test
TEST(core_test, is_formattable) { TEST(core_test, is_formattable) {
#if 0 #if 0
@ -796,7 +805,9 @@ TEST(core_test, is_formattable) {
struct s; struct s;
static_assert(!fmt::is_formattable<int(s::*)>::value, ""); static_assert(!fmt::is_formattable<int(s::*)>::value, "");
static_assert(!fmt::is_formattable<int (s::*)()>::value, ""); static_assert(!fmt::is_formattable<int (s::*)()>::value, "");
static_assert(!fmt::is_formattable<test_scoped_enum>::value, ""); static_assert(!fmt::is_formattable<unformattable_scoped_enum>::value, "");
static_assert(fmt::is_formattable<test::formattable_scoped_enum>::value, "");
static_assert(!fmt::is_formattable<test::convertible_to_enum>::value, "");
} }
TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); } TEST(core_test, format) { EXPECT_EQ(fmt::format("{}", 42), "42"); }
@ -807,6 +818,10 @@ TEST(core_test, format_to) {
EXPECT_EQ(s, "42"); EXPECT_EQ(s, "42");
} }
TEST(core_test, format_as) {
EXPECT_EQ(fmt::format("{}", test::formattable_scoped_enum()), "42");
}
struct convertible_to_int { struct convertible_to_int {
operator int() const { return 42; } operator int() const { return 42; }
}; };