Make fmt::as_identifiers a struct instead of a variable - #4900
Conversation
|
Note: this logically conflicts with #4899. If you want both (and you should), merge one and I'll refresh the other. |
1a9f487 to
5daa812
Compare
|
v2:
|
5daa812 to
f1c7aa7
Compare
|
v3:
|
The annotation was a constant of an empty type, which left no room for
options. Make the annotation type itself, fmt::as_identifiers, the thing
users write, so it is now spelled
enum class [[=fmt::as_identifiers()]] color { red, green, blue };
and options can later be added as constructor arguments.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
f1c7aa7 to
cb60c61
Compare
|
v4:
|
|
What kind of options do you envision? |
|
Let's say one's coding style is scary ENUM_OPTION_1 but one doesn't want to inflict it on one's users. One then writes |
|
I also expect something like [[=fmt::format_as("alternative")]] when a particular identifier isn't suitable, but that isn't on the enum type itself. |
|
Also: |
vitaut
left a comment
There was a problem hiding this comment.
I think we should keep the common case simple. If configurability is needed later, it could either use a separate API or make as_identifiers callable, for example:
struct as_identifiers_t {
// Future state/options...
constexpr auto operator()(/* options */) const -> as_identifiers_t {
return {/* ... */};
}
};
inline constexpr auto as_identifiers = as_identifiers_t();Then the simple case remains:
[[=fmt::as_identifiers]]while allowing something like this later:
[[=fmt::as_identifiers(fmt::enum_case::lower)]]I’m also somewhat skeptical about the lowercase use case specifically, so I wouldn’t make the common syntax more verbose today in anticipation of that kind of configurability.
|
I think it's better to avoid cleverness in a widely-used interface. If people see that as_identifiers sometimes look like a variable, and sometimes like constructor, it will be harder to build a mental model of what's going on. There's a place for those tricks, like when retrofitting something set in stone, but I think it's out of place for a new design. It also prevents usage of designated initializers. If we keep the inline variable approach, then it's better to use a separate name for the constructor (e.g. =as_identifers_t{...}) About the actual options, I don't see any rush to implement them, but I think it's prudent to be prepared. |
|
I'm fine with a separate name. In any case, I'm going to close this PR since keeping inline variables for the common case means that we can decide on callable vs separate name later, when the options are actually needed. |
|
Ok |
The annotation was a constant of an empty type, which left no room for options. Make the annotation type itself, fmt::as_identifiers, the thing users write, so it is now spelled
enum class [[=fmt::as_identifiers()]] color { red, green, blue };
and options can later be added as constructor arguments.