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

Support no default value enum_switch #199

Closed
Sarna555 opened this issue Jul 11, 2022 · 12 comments
Closed

Support no default value enum_switch #199

Sarna555 opened this issue Jul 11, 2022 · 12 comments
Labels
enhancement New feature or request

Comments

@Sarna555
Copy link

would it be possible to support enum_switch the way that we're used to use overload pattern with std::visit?
e.g

return magic_enum::enum_switch( overloaded{
           []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
           []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
});

instead of

return magic_enum::enum_switch( overloaded{
           []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
           []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
}, /*redundant default*/ int(2));

// or probably worse

auto r = magic_enum::enum_switch(
           []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; }
           , int(2)
);

if( r == 2 ) throw notimplemented;

I think forcing adding default Result produces boilerplate.

@Neargye
Copy link
Owner

Neargye commented Jul 11, 2022

If you need to iterate over all values ​​then use enum_for_each

enum_switch does not take a default value, it takes a value that will be handled in the switch

@Sarna555
Copy link
Author

Sarna555 commented Jul 12, 2022

Yes, sorry I made a mistake in the example above.

return magic_enum::enum_switch( overloaded{
           []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
           []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
}, enumValue);

I'm taking about return value of enum_switch
from docs

template <typename Result = void, typename E, typename Lambda>
constexpr Result enum_switch(Lambda&& lambda, E value);

template <typename Result, typename E, typename Lambda>
constexpr Result enum_switch(Lambda&& lambda, E value, Result&& result);

If I want to return a value from enum_switch (Result is not void) I need to pass additional argument and It'd be nice not being forced to do so.

@Neargye
Copy link
Owner

Neargye commented Jul 12, 2022

return magic_enum::enum_switch<int>( overloaded{
           []( my_enum::val1 arg ) -> int { /* handle val1 enum */ return 1; },
           []( auto arg ) -> int { /* handle the rest */ throw notimplemented; /* or just return sth */ }
}, enumValue);

see https://github.com/Neargye/magic_enum/blob/master/example/example_switch.cpp

@Sarna555
Copy link
Author

ok, but I still need to specify the return type explicitly.
In case of std::visit as long as all the lambdas in overload return the same value there is no need for additional code.

std::visit( overloaded { []( const Type1 val ) { return int(1); }, 
                         []( const Type2 val ) { return float(2); }
           }); // compilation error

std::visit( overloaded { []( const Type1 val ) { return int(1); }, 
                         []( const Type2 val ) -> int { return float(2); }
           }); // fine

std::visit( overloaded { []( const Type1 val ) { return int(1); }, 
                         []( const Type2 val ) { return int(2); }
           }); // fine

@Neargye
Copy link
Owner

Neargye commented Jul 12, 2022

I'll see what i can do

@Neargye Neargye added the enhancement New feature or request label Jul 12, 2022
@Neargye Neargye added this to the 0.8.2 milestone Jul 12, 2022
@schaumb
Copy link
Contributor

schaumb commented Jul 21, 2022

The switch is not required to handle all cases (especially unrecognized values), so when explicitly isn't set the result (or the type) for the magic_enum::enum_switch call, the result type cannot be guessed for all case return value.


What will be the result for example 4 different result type without explicitly set the result? std::common_type<R1, R2 ...>? And if it isn't constructible, or a base class?
What will be the result of any unrecognized (unnamed) enum value? How can be handle this? This will cause error message, when the result type is not default constructible.

What if someone didn't handle all case, and lambda can't be instantiated with some value?

Many unanswered question will come up if we enable enum_switch result type deduction from only the callback.


So the current rule is:
If you explicit set the type, you are the responsible to this type can be default construct.
If you want to use result type that cannot be default construct, you have to pass the default result object.
Else, the switch return void.

and there are no "better" way to do otherwise.

@Neargye
Copy link
Owner

Neargye commented Aug 8, 2022

@schaumb
I like the option to make it consistent with the std::visit, so that there is a fallback for all possible enums or defaults.
This is also consistent with the enum warnings switch that you need to case all values ​​or the default case.

If you don't mind, I can add the necessary traits for the checks inside the function.

@schaumb
Copy link
Contributor

schaumb commented Aug 9, 2022

If I wrote a swich, I don't need to write all case / default.

I think this is an another use-case, and probably not a switch but a visit.
I think this can be a different function which uses enum_switch with type-traits check, to handle all case + default, and guess the result type.

enum_visit ?

@Neargye Neargye removed this from the 0.8.2 milestone Aug 12, 2022
@Neargye
Copy link
Owner

Neargye commented Sep 2, 2022

@Sarna555 #212 I tried to improve the deduction of the return type of the enum_switch, but the function signature changed a little

enum_switch will try to deduce return the type, if this is not possible, then you still need have to specify the return type explicitly

@Sarna555
Copy link
Author

Sarna555 commented Sep 7, 2022

@Sarna555 #212 I tried to improve the deduction of the return type of the enum_switch, but the function signature changed a little

enum_switch will try to deduce return the type, if this is not possible, then you still need have to specify the return type explicitly

Yes, this is what I meant, not having to specify the return type.
Is it something that could be merged to the master branch and released?

@Neargye
Copy link
Owner

Neargye commented Sep 7, 2022

@Sarna555 #212 I tried to improve the deduction of the return type of the enum_switch, but the function signature changed a little
enum_switch will try to deduce return the type, if this is not possible, then you still need have to specify the return type explicitly

Yes, this is what I meant, not having to specify the return type. Is it something that could be merged to the master branch and released?

I'll take it to the master and release after some additional testing.

@Neargye Neargye closed this as completed in 8bd403f Nov 7, 2022
@Neargye
Copy link
Owner

Neargye commented Nov 7, 2022

Fix in master
Will be include in next release

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

No branches or pull requests

3 participants