Skip to content

Add prefix trimming #414

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open

Conversation

ZXShady
Copy link
Contributor

@ZXShady ZXShady commented Jun 12, 2025

Implements #402 Sorry @durka for the later than promised PR!

@lsemprini can you tell me what should I do with ADL info? I didn't want to add a third integral parameter I think that would be too confusing or what do you think?

Is the docs alright Daniil? I don't know how to write a decent one.

I don't have a setting to keep the prefix if turned of explicitly.

is that needed?

@lsemprini
Copy link
Contributor

Implements #402 Sorry @durka for the later than promised PR!

@lsemprini can you tell me what should I do with ADL info? I didn't want to add a third integral parameter I think that would be too confusing or what do you think?

DEFINITELY prefix_length needs to be settable by ADL too! Anything that is in enum_range should be settable by either customize specialization or ADL. Otherwise there is no way to use the feature for enums that are deep inside namespaces, and prefix-length is just as useful in that case. It would be confusing and odd not to have all the enum_range parameters consistently available by either customize specialization or ADL.

As far as the adl_info shorthand struct, if we are going to have adl_info, then it should be able to provide shorthand for any of the features of enum_range. The advantage of adl_info is you don't have to define any struct. The disadvantage of adl_info is you cannot combine settings of is_flags, min/max, or prefix_length. For adl_info may I suggest renaming them to adl_magic_enum_range_is_flags, adl_magic_enum_range_min_max, and adding adl_magic_enum_range_prefix_length so that it is more clear what they do when people read code, and what the parameters mean, and so that the integer of prefix_length no longer conflicts with the bool of is_flags ? That way, we don't have to be at the mercy of having different C types.

Is the docs alright Daniil? I don't know how to write a decent one.

We would need to add more docs to limitations.md and change the existing docs for is_flags and min/max a little.

I am happy to do that after you have finalized what the code/API should be like.

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 12, 2025

Implements #402 Sorry @durka for the later than promised PR!

@lsemprini can you tell me what should I do with ADL info? I didn't want to add a third integral parameter I think that would be too confusing or what do you think?

DEFINITELY prefix_length needs to be settable by ADL too! Anything that is in enum_range should be settable by either customize specialization or ADL. Otherwise there is no way to use the feature for enums that are deep inside namespaces, and prefix-length is just as useful in that case. It would be confusing and odd not to have all the enum_range parameters consistently available by either customize specialization or ADL.

As far as the adl_info shorthand struct, if we are going to have adl_info, then it should be able to provide shorthand for any of the features of enum_range. The advantage of adl_info is you don't have to define any struct. The disadvantage of adl_info is you cannot combine settings of is_flags, min/max, or prefix_length. For adl_info may I suggest renaming them to adl_magic_enum_range_is_flags, adl_magic_enum_range_min_max, and adding adl_magic_enum_range_prefix_length so that it is more clear what they do when people read code, and what the parameters mean, and so that the integer of prefix_length no longer conflicts with the bool of is_flags ? That way, we don't have to be at the mercy of having different C types.

I mean I can add a third optional parameter for adl_info

adl_info<-10,10> // min,max
adl_info<true> // is_flags
adl_info<true,10> // is_flags + prefix length
adl_info<-10,10,10> // min,max + prefix length

as you noticed I don't have adl_info<10> to mean prefix_length this is intentional if you override prefix_length you should override min max anyways and why I force overriding min max if you just want to override prefix length.

I don't want to go 3 adl functions route since it will slow down compilation unnecessarily (not by much given how expensive magic enum is relative to 3 adl calls)

We can split the adl_info into 2 structs adl_info_flags and adl_info_minmax this way it is clearer than a simple boolean type to differentaite

Is the docs alright Daniil? I don't know how to write a decent one.

We would need to add more docs to limitations.md and change the existing docs for is_flags and min/max a little.

I am happy to do that after you have finalized what the code/API should be like.

sure.

@lsemprini
Copy link
Contributor

I mean I can add a third optional parameter for adl_info...
as you noticed I don't have adl_info<10> to mean prefix_length this is intentional if you override prefix_length you should override min max anyways and why I force overriding min max if you just want to override prefix length.

Ok now I understand the goal. Why is it necessary to provide min/max if you want to provide prefix_length? Is that a limitation of the implementation?

I don't want to go 3 adl functions route since it will slow down compilation unnecessarily (not by much given how expensive magic enum is relative to 3 adl calls)

To be clear, I wasn't proposing having 3 ADL functions. The ADL function (the function that magic_enum finds by ADL lookup) would still be just one function adl_magic_enum_define_range() and it would return 1 struct with up to all 4 params in it (is_flags, min/max, prefix_length).

Instead, I was just proposing renaming adl_info to make it more clear what the parameters mean, to someone reading code with adl_info in it.

We can split the adl_info into 2 structs adl_info_flags and adl_info_minmax this way it is clearer than a simple boolean type to differentaite

How about splitting adl_info into adl_info_is_flags adl_info_minmax and adl_info_minmax_prefix_length? Then every use of the templates will document what the parameters mean to someone reading the code.

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 12, 2025

I mean I can add a third optional parameter for adl_info...
as you noticed I don't have adl_info<10> to mean prefix_length this is intentional if you override prefix_length you should override min max anyways and why I force overriding min max if you just want to override prefix length.

Not a limitation but if you know the prefix length then why not set the min max as well? this is what I do in my library,

if you want the default anyway, set the max to MAGIC_ENUM_RANGE_MAX.

Ok now I understand the goal. Why is it necessary to provide min/max if you want to provide prefix_length? Is that a limitation of the implementation?

I don't want to go 3 adl functions route since it will slow down compilation unnecessarily (not by much given how expensive magic enum is relative to 3 adl calls)

To be clear, I wasn't proposing having 3 ADL functions. The ADL function (the function that magic_enum finds by ADL lookup) would still be just one function adl_magic_enum_define_range() and it would return 1 struct with up to all 4 params in it (is_flags, min/max, prefix_length).

Instead, I was just proposing renaming adl_info to make it more clear what the parameters mean, to someone reading code with adl_info in it.

We can split the adl_info into 2 structs adl_info_flags and adl_info_minmax this way it is clearer than a simple boolean type to differentaite

How about splitting adl_info into adl_info_is_flags adl_info_minmax and adl_info_minmax_prefix_length? Then every use of the templates will document what the parameters mean to someone reading the code.

I think having 2 for is_flags and minmax and prefix length being the last optional parameter.

having 4 combinations (you missed is_flags_prefix_length) seems a lot

@lsemprini
Copy link
Contributor

How about splitting adl_info into adl_info_is_flags adl_info_minmax and adl_info_minmax_prefix_length? Then every use of the templates will document what the parameters mean to someone reading the code.

I think having 2 for is_flags and minmax and prefix length being the last optional parameter.

It would work for now, but it's unintuitive when reading code that uses it, and as we add more features into the struct returned by the ADL func in the future (e.g. we're adding prefix_length now and will probably add more fields in the future), there will be more and more combinations. Is there some way to rejigger adl_info to cleanly document itself and not have to cover all combinations? e.g. something like adl_info().is_flags(true).minmax(-10,20).prefix_length(4) but that can generate the required static constexpr fields at compile time?

Also worth considering: maybe just delete adl_info entirely? It was a cool idea but it is essentially just an optional shorthand; maybe it's less and less helpful as there are more and more params in the struct returned by the ADL func?

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 12, 2025

How about splitting adl_info into adl_info_is_flags adl_info_minmax and adl_info_minmax_prefix_length? Then every use of the templates will document what the parameters mean to someone reading the code.

I think having 2 for is_flags and minmax and prefix length being the last optional parameter.

It would work for now, but it's unintuitive when reading code that uses it, and as we add more features into the struct returned by the ADL func in the future (e.g. we're adding prefix_length now and will probably add more fields in the future), there will be more and more combinations. Is there some way to rejigger adl_info to cleanly document itself and not have to cover all combinations? e.g. something like adl_info().is_flags(true).minmax(-10,20).prefix_length(4) but that can generate the required static constexpr fields at compile time?

Also worth considering: maybe just delete adl_info entirely? It was a cool idea but it is essentially just an optional shorthand; maybe it's less and less helpful as there are more and more params in the struct returned by the ADL func?

something like magic_enum::adl_info().is_flags<true>().minmax<-100,100>().prefix_length<8>() and would work

auto adl_magic_enum_range(Enum)
{
    return magic_enum::adl_info().is_flags<true>().minmax<-100,100>().prefix_length<8>();
}

@lsemprini
Copy link
Contributor

That would be cool! Is there a way to make it work and have the members be static constexpr ?

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 12, 2025

That would be cool! Is there a way to make it work and have the members be static constexpr ?

template<bool IsFlags = false,int Min = MAGIC_ENUM_RANGE_MIN,int Max = MAGIC_ENUM_RANGE_MAX,std::size_t PrefixLength = 0>
struct adl_info_holder {
    constexpr static int max = Max;
    constexpr static int min = Min;
    constexpr static bool is_flags =IsFlags;
    constexpr static std::size_t prefix_length = PrefixLength;
  
    template<int min,int max>
    static adl_info_holder<IsFlags,min,max,PrefixLength> minmax() { return {};}
     template<bool flag>
     static adl_info_holder<flag,Min,Max,PrefixLength> flag() { return {};}

     template<std::size_t PrefixLen>
     static adl_info_holder<IsFlags,Min,Max,PrefixLen> prefix() { return {};}

};

adl_info_holder<> adl_info()
{
     return {};
}

@lsemprini
Copy link
Contributor

Neat!

@lsemprini
Copy link
Contributor

Let me know when you've got your final code changes in and I'll do documentation

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 15, 2025

Let me know when you've got your final code changes in and I'll do documentation

I am waiting for Neargye f
opinion first

@Neargye
Copy link
Owner

Neargye commented Jun 24, 2025

Hi @ZXShady
For me, it looks good!

not critical, but from my logic we can simply name std::size_t prefix_length - If there is no need to remove the prefix, then it will logically be zero.

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 25, 2025

Hi @ZXShady
For me, it looks good!

not critical, but from my logic we can simply name std::size_t prefix_length - If there is no need to remove the prefix, then it will logically be zero.

it is not required to be defined as in the docs

  • prefix_length tells magic_enum how many characters to remove from the start of the names for all string functions. It is not required to be defined if not defined it will be assumed to be 0

@Neargye
Copy link
Owner

Neargye commented Jun 26, 2025

Is PR ready to merge?

@lsemprini
Copy link
Contributor

lsemprini commented Jun 27, 2025 via email

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 27, 2025

I think it is fine to merge this then we can in a later pr revamp the adl info struct or just remove it entirely

@lsemprini
Copy link
Contributor

lsemprini commented Jun 27, 2025 via email

@lsemprini
Copy link
Contributor

In other words, if you compare line 176 and line 189 of

https://github.com/ZXShady/magic_enum/blob/add_prefix_length/include/magic_enum/magic_enum.hpp

the is_flags stuff checks ADL but the prefix_length stuff does not check ADL.

Is that the correct source we are considering merging, or am I looking in the wrong place?

@ZXShady
Copy link
Contributor Author

ZXShady commented Jun 27, 2025

In other words, if you compare line 176 and line 189 of

https://github.com/ZXShady/magic_enum/blob/add_prefix_length/include/magic_enum/magic_enum.hpp

the is_flags stuff checks ADL but the prefix_length stuff does not check ADL.

Is that the correct source we are considering merging, or am I looking in the wrong place?

you are right indeed it ignores prefix_length adl right now.

a fix is simple adding this line

template<class E>
constexpr auto prefix_length_or_zero<T,std::void_t<decltype(decltype(adl_magic_enum_define_range(E{}))::prefix_length)>> = std::size_t{decltype(adl_magic_enum_define_range(E{}))::prefix_length};

I can't currently do this as I have extremely bad internet for the next week or so

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants