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

Enumerant initialization from previous enumerant values #5

Open
jesse-k opened this issue Nov 9, 2020 · 1 comment
Open

Enumerant initialization from previous enumerant values #5

jesse-k opened this issue Nov 9, 2020 · 1 comment

Comments

@jesse-k
Copy link

jesse-k commented Nov 9, 2020

I realize you may not be maintaining this library currently, but I may have found a bug, and I'd be remiss in not sharing the information.

It seems the Meta Enum member values may not be correct if an enumerant is initialized using the value of a previous enumerant. Here's a self-contained example:

#include <iostream>

#include "meta_enum.hpp"

meta_enum_class(Enum, int, a, b, c = b, d);

std::ostream & operator<<(std::ostream & stream, Enum const value) {
    return stream << static_cast<int>(value);
}

int main(int const argc, char * const argv[]) {
    std::cout << "Expected values : ";
    std::cout << Enum::a << Enum::b << Enum::c << Enum::d << std::endl;
    
    std::cout << "Meta Enum values: ";
    for (auto const & member : Enum_meta.members) {
        std::cout << member.value;
    }
    std::cout << std::endl;
}

Output:

Expected values : 0112
Meta Enum values: 0123

I think the issue is in the 'Type##_internal_size' function. With this approach, the int wrapper for 'b' is empty, and when the int wrapper for 'c' is created, it's empty too. So the method being used there doesn't seem to be able to account for assignment from previous enumerants (unless I'm mistaken).

I stumbled across this while trying some different enum libraries and doing some experimenting of my own. If I manage to solve this particular problem in my own code, I'll try to post back.

@jesse-k
Copy link
Author

jesse-k commented Nov 9, 2020

I'll offer one more comment here with a few additional observations.

It might be that there are more issues related to initialization apart from what I mentioned above. For example, this works:

enum class Enum : int { a, b, c = []() { return b; }(), d };

But this:

meta_enum_class(Enum, int, a, b, c = []() { return b; }(), d);

Fails because the lambda doesn't capture 'b' in 'Type##_internal_size'.

To further complicate matters, you can do this:

enum class Enum : int { a [[maybe_unused]], b, c, d };

But not this:

meta_enum_class(Enum, int, a [[maybe_unused]], b, c, d);

Perhaps there are solutions here, but maybe there are just some limitations to this particular approach.

Edit: Let me add that I don't mean to imply these are faults with the library. These seem like difficult problems to solve (especially without making extensive use of the preprocessor). And, the only one of these issues that's likely to come up in practice would be simple initialization from previous enumerants, e.g. 'c = b + 2'. The other issues (lambdas, attributes) are more just curiosities.

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

1 participant