Open JaapAap opened 7 years ago
I think it's ultimately a matter of preference. I think something close to what you are proposing is also discussed in Should Better Enums provide enum "objects" or traits types? Depending on what exactly you'd like to do, there may be some small technical limitations. I think you're proposing something between the current "object" interpretation and a full-on traits-only interpretation, so to answer your question usefully, I'd (we'd) have to look in total at what would be implemented where and how.
You're welcome to experiment. You can use that question as a list of things to watch out for – I think it's all I know. You can also glance in the branch that the question mentions. Though the branch is quite outdated, it's good enough to get an idea everything that needs to go into a partial- or full-traits implementation.
In particular, the make_enum
factory would probably conflict with declaring enums inside namespaces, and would need some kind of workaround. It's probably solvable with a combination of private data/static methods in objects, and maybe some kind of friend traits class.
Regarding the specific choices:
from_string
function, rather than converting constructors.from_string
to conflate conversion with mutation. Better Enums are supposed to mimic language enums and other basic language types. This actually makes me want to go back and make even more functions static.from_string
should work even if there is no object yet. from_string
is logically the enum constructor that converts from strings. It's just not a C++ in-language constructor, but an explicitly-named one obtained by abusing a static function.It's pretty unfortunate that C++ allows calling from_string
as if it were a non-static function. I'd love to disallow that somehow, given the above interpretation.
The stuff above is suited to how I, and some proportion of C++ programmers, think about code. If it hurts you, you're welcome to modify the library. If you think it will be definitively better, a discussion or, even PR, would be quite welcome :)
Thanks for that, I think I understand your arguments. Indeed, it would not be much of an issue if the compiler could prevent the static function being called on objects somehow. Just for my understanding, what is the reason for having case sensitive and case insensitive versions of the _from_string factory function? Isn't this dangerous as the _enumeration is in fact case sensitive and could have both "A" and "a" as valid values?
The strongest justification (not that strong) is that the wider project that spawned Better Enums needed both kinds of string conversion. Beyond that reason, it's only that it might be useful for someone else. I suppose at this point, case-insensitive conversion could be removed, if there is suitably large advantage in doing that.
Case-insensitive conversion is slightly dangerous, but I don't think it's particularly dangerous relative to what else can happen with enums. For example, converting from an integer is approximately as dangerous, because two enum constants might have the same numeric value.
Well, it's a different kind of danger. The result of conversion will be correct for the ambiguous from_integer
conversion, but potentially incorrect for the ambiguous from_string_nocase
conversion. Round-trips can be broken in both cases.
I am migrating from a 'smart enum' library based on what used to be 'BOOST_ENUM'. I noticed that the _from_string function is static, and recall having been bitten by this before in that library.
My problem is that it is possible to call this as a member function on an existing enumeration with rather unpleasant consequences.
I would much prefer the function to be non-static, in order to make sure that at the end
X == Enum::B
holds, and (for example) having a factory function akin to what is present in the standard library, such as:Also, I am missing constructors that allow for example:
Enum X("A")
Is there a good reason to not allow this?