Skip to content
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

Traits class #21

Open
cheparukhin opened this issue Jun 21, 2016 · 15 comments
Open

Traits class #21

cheparukhin opened this issue Jun 21, 2016 · 15 comments
Milestone

Comments

@cheparukhin
Copy link
Collaborator

I would be nice to have a traits class to detect whether a type is a "better enum" (akin to std::is_enum)

@aantron
Copy link
Owner

aantron commented Jun 21, 2016

Agreed, this would be nice. However, I don't think I can just do it in the obvious way, using template specialization:

namespace better_enums {

template <typename T>
struct _is_better_enum_value {
    constexpr static const bool    value = false;
};

template <typename T>
struct is_better_enum : public _is_better_enum_value<T> {
    // Standard members: type, value_type, operator bool, operator ().
};

}
// The specialization, generated by the macro...

template <>
struct _is_better_enum_value {
    constexpr static const bool    value = true;
};

because the specialization does not occur, in general, in a namespace that encloses the original template declaration. So, if you do

namespace my_ns {
    BETTER_ENUM(Foo, int, bar)
}

you will get an error, since my_ns is not better_enums or the global namespace.


There is probably some way to do this with SFINAE, by checking a specially-named member of generated enums. This is a bit fragile, but should be pretty easy in C++11. I am not sure if it can work in C++98, though – C++98 is a bit out of my brain's cache right now.

I'm a bit overwhelmed by other work at the moment, but I will look into it later. You are welcome to comment as well :)

@cheparukhin
Copy link
Collaborator Author

cheparukhin commented Jun 21, 2016

@aantron I currently implemented it in my code using SFINAE checking _to_integral member function, but it seems a bit hacky. I was wondering if you can derive enum classes from a common base and then use std::is_base_of to check if a class is an enum.

#include <type_traits>
#include <utility>

template <typename T, typename = void>
struct IsBetterEnum
    : std::false_type {};

template <typename T>
struct IsBetterEnum<T, decltype(std::declval<T>()._to_integral(), void())>
    : std::true_type {};

@aantron
Copy link
Owner

aantron commented Jun 21, 2016

All those could work, but if implemented literally that way, they would require C++11. While I've been thinking on and off about dropping C++98 support, I think it's better to keep it for as long as reasonably possible.

I'm pretty sure std::is_base_of, or a type member check, or something, can be implemented using only C++98 constructs – I'm just so out of practice with C++98, and constrained, that I can't do it in the really near future :/ If you can adapt your approach above to something that doesn't use <type_traits>, decltype, and so forth, and compiles with your compiler's C++98 flags, a PR would be very welcome :)

Deriving all enums from a base class should be fine. Adding some less collision-prone member value or type, such as _is_better_enum, is also fine.

@cheparukhin
Copy link
Collaborator Author

@aantron I've only been using C++11 for the last 5 years at least, so I don't think I can help with C++98. I wonder if there's any particular reason for C++98 support? I can hardly imagine someone using it for new code nowadays :) Could it be provided as C++11-only feature?

@aantron
Copy link
Owner

aantron commented Jun 22, 2016

Yep, it can be provided as a C++11-only feature, and might have to be. I'd still like to try to adapt it to C++98 first, though, so If you don't mind the upstream not having this for a while, then let me get around to it. It's definitely on the list of things I want to add :)

As for C++98, I think a lot of people are stuck in old code bases. They might still want a nicer enum :)

I'm actually planning to take advantage of some C++14 features, too, when I next have the time for a burst of work on Better Enums. I may be removing C++98 at that point, if supporting all 3 standards gets too cumbersome.

@aantron
Copy link
Owner

aantron commented Jul 7, 2016

Following on #22, if MSVC has had a <type_traits> supporting the features we need, and whatever combination of decltype and/or declval, for "long enough" (since, maybe, mid-2015), we can move away from needing a C++98 implementation, and implement the traits class you are requesting using those C++11 features. If you can confirm that, then a PR/commit is very welcome.

@ecorm
Copy link

ecorm commented Mar 7, 2017

For those of use willing to use C++11 features, is there a way we can write our own macro that wraps BETTER_ENUM and provides the necessary plumbing for a is_better_enum<T>::value trait? The lack of such a is_better_enum<T>::value trait is preventing us from replacing our hand-written enum<-->string maps with your library.

@ecorm
Copy link

ecorm commented Mar 7, 2017

Could extra/better-enums/n4428.h be used for this purpose?

@aantron
Copy link
Owner

aantron commented Mar 7, 2017

You should be able to write ordinary variable-argument macros wrapping BETTER_ENUM that do any extra work that you need. Are you having difficulties with that?

In the meantime, I'm tending towards finally dropping C++98 the next time I have hours to work on Better Enums.

@ecorm
Copy link

ecorm commented Mar 7, 2017

You should be able to write ordinary variable-argument macros wrapping BETTER_ENUM that do any extra work that you need. Are you having difficulties with that?

I haven't tried yet. I never had to write variable-argument macros before and just wanted to check that it was even possible before attempting it.

@tallavi
Copy link

tallavi commented Sep 20, 2017

+1 for deriving the types from a common base type, so I can develop functionality that works on all enum types without using templates!

@morgoth990
Copy link

deriving the types from a common base type can help me too, I'm working on a generic object inspector and is the only way to draw a generic gui without manage every specific enum type from code

@Xeverous
Copy link
Contributor

Xeverous commented Mar 4, 2019

Just a bump noting that there are more people interested in is_better_enum trait. I was surprised when I realized that std::is_enum_v<BetterEnumType> == false. This means that the "upgrade" from C++11 enums to better enums can actually result in build failures.

@aantron
Copy link
Owner

aantron commented Mar 11, 2019

Noted! I really need to get around to doing this.

@aantron aantron added this to the 0.11.3 milestone Aug 17, 2019
@gri6507
Copy link

gri6507 commented Nov 4, 2022

I am also interested in this functionality. I see that this issue was added to 0.11.3 milestone, but 0.11.3 is already released. Does this mean that this feature has not been implemented yet?

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

No branches or pull requests

7 participants