diff --git a/CMakeLists.txt b/CMakeLists.txt index 705fe463b273..01b282dbf999 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -414,7 +414,7 @@ endfunction () set(FMT_REFLECTION_TEST_CODE " #include - enum class [[=fmt::as_identifiers]] color { red }; + enum class [[=fmt::as_identifiers()]] color { red }; static_assert(fmt::is_formattable::value, \"\"); int main() {} ") diff --git a/doc/api.md b/doc/api.md index fb39083ec7c5..131f2f1208f5 100644 --- a/doc/api.md +++ b/doc/api.md @@ -566,7 +566,7 @@ enumerator matching the formatted value: #include - enum class [[=fmt::as_identifiers]] color { red, green, blue }; + enum class [[=fmt::as_identifiers()]] color { red, green, blue }; fmt::print("{}", color::green); // Output: green diff --git a/include/fmt/enum.h b/include/fmt/enum.h index bbe1a18ff4eb..92ea8ea8bc92 100644 --- a/include/fmt/enum.h +++ b/include/fmt/enum.h @@ -32,21 +32,18 @@ FMT_BEGIN_NAMESPACE #if FMT_USE_REFLECTION -/// The type of the `fmt::as_identifiers` annotation. -FMT_EXPORT struct as_identifiers_t {}; - /** * An annotation that makes an enum format as identifiers of its enumerators. * * **Example**: * - * enum class [[=fmt::as_identifiers]] color { red, green, blue }; + * enum class [[=fmt::as_identifiers()]] color { red, green, blue }; * auto s = fmt::format("{}", color::green); // s == "green" * * A value that doesn't match any enumerator is represented as its underlying * value in decimal before applying string formatting. */ -FMT_EXPORT inline constexpr auto as_identifiers = as_identifiers_t(); +FMT_EXPORT struct as_identifiers {}; namespace detail { @@ -56,8 +53,7 @@ consteval auto use_identifiers() -> bool { if constexpr (!std::is_enum::value) { return false; } else { - return !std::meta::annotations_of_with_type(^^U, ^^as_identifiers_t) - .empty(); + return !std::meta::annotations_of_with_type(^^U, ^^as_identifiers).empty(); } } diff --git a/test/enum-test.cc b/test/enum-test.cc index b424ef782f1b..ed21e6b9422a 100644 --- a/test/enum-test.cc +++ b/test/enum-test.cc @@ -21,56 +21,61 @@ TEST(enum_test, no_reflection) { // clang-format doesn't support annotations yet. // clang-format off -enum class [[=fmt::as_identifiers]] color { red, green, blue }; +enum class [[=fmt::as_identifiers()]] color { red, green, blue }; enum class color_without_annotation { red, green, blue }; -enum [[=fmt::as_identifiers]] unscoped_color { unscoped_red, unscoped_green }; -enum class [[=fmt::as_identifiers]] level : unsigned char { low = 1, high = 2 }; -enum class [[=fmt::as_identifiers]] byte_enum : char { one = 1 }; -enum class [[=fmt::as_identifiers]] signed_byte_enum : signed char { minus_one = -1 }; -enum class [[=fmt::as_identifiers]] bool_enum : bool { off = false }; -enum class [[=fmt::as_identifiers]] alias { one = 1, uno = 1 }; -enum class [[=fmt::as_identifiers]] empty_enum {}; +enum [[=fmt::as_identifiers()]] unscoped_color { unscoped_red, unscoped_green }; +enum class [[=fmt::as_identifiers()]] level : unsigned char { + low = 1, + high = 2 +}; +enum class [[=fmt::as_identifiers()]] byte_enum : char { one = 1 }; +enum class [[=fmt::as_identifiers()]] signed_byte_enum : signed char { + minus_one = -1 +}; +enum class [[=fmt::as_identifiers()]] bool_enum : bool { off = false }; +enum class [[=fmt::as_identifiers()]] alias { one = 1, uno = 1 }; +enum class [[=fmt::as_identifiers()]] empty_enum {}; // Dense values: formatted via a lookup table. -enum class [[=fmt::as_identifiers]] dense { d0, d1, d2, d3, d4 }; +enum class [[=fmt::as_identifiers()]] dense { d0, d1, d2, d3, d4 }; // 3 holes out of 10: the sparsest case that still uses a lookup table. -enum class [[=fmt::as_identifiers]] holey { +enum class [[=fmt::as_identifiers()]] holey { h0, h1, h2, h3, h4, h5, h6 = 9 }; // 4 holes out of 11: just too sparse, formatted via a hash table. -enum class [[=fmt::as_identifiers]] sparse { +enum class [[=fmt::as_identifiers()]] sparse { s0, s1, s2, s3, s4, s5, s6 = 10 }; // Values spanning both signs and the extremes of the underlying type. -enum class [[=fmt::as_identifiers]] signed_enum { +enum class [[=fmt::as_identifiers()]] signed_enum { minus_two = -2, minus_one = -1, one = 1 }; // Many scattered values, exercising collisions in the hash table. -enum class [[=fmt::as_identifiers]] scattered { +enum class [[=fmt::as_identifiers()]] scattered { a = 1, b = 17, c = 33, d = 49, e = 65, f = 81, g = 97, h = 113, i = 129, j = 145, k = 161, l = 177 }; // Values that collide in the hash table: c0, c7 and c15 share a slot, and c6 // occupies the next one, so probing for c7 and c15 has to step over it. -enum class [[=fmt::as_identifiers]] collision { +enum class [[=fmt::as_identifiers()]] collision { c0 = 0, c6 = 6, c7 = 7, c15 = 15 }; // Values that collide in the last slot of the hash table, so the probe // sequence wraps around to the beginning. -enum class [[=fmt::as_identifiers]] wrapping_collision { +enum class [[=fmt::as_identifiers()]] wrapping_collision { w8 = 8, w16 = 16, w24 = 24 }; // Aliased values in an enum that is too sparse for a lookup table. -enum class [[=fmt::as_identifiers]] sparse_alias { +enum class [[=fmt::as_identifiers()]] sparse_alias { one = 1, dup = 1, far = 1000 }; -enum class [[=fmt::as_identifiers]] extremes : int { +enum class [[=fmt::as_identifiers()]] extremes : int { lowest = INT_MIN, highest = INT_MAX }; -enum class [[=fmt::as_identifiers]] big : unsigned long long { +enum class [[=fmt::as_identifiers()]] big : unsigned long long { huge = ULLONG_MAX }; // clang-format on diff --git a/test/module-test.cc b/test/module-test.cc index e266a8797e98..57f9534c39e6 100644 --- a/test/module-test.cc +++ b/test/module-test.cc @@ -377,7 +377,7 @@ TEST(module_test, compile_format_string) { defined(__cpp_lib_define_static) // clang-format doesn't support annotations yet. // clang-format off -enum class [[=fmt::as_identifiers]] color { red, green, blue }; +enum class [[=fmt::as_identifiers()]] color { red, green, blue }; // clang-format on TEST(module_test, format_enum) {