5 ms·
Something simpler is to put all bitmask enums in a namespace and use ADL to find the operators. Like this: https://pastebin.com/raw/ANh93JnN https://pastebin.co
by pubby 8y ago
Something simpler is to put all bitmask enums in a namespace and use ADL to find the operators. Like this: https://pastebin.com/raw/ANh93JnN https://pastebin.com/raw/ANh93JnN
Personally though, I wouldn't use this safety in most code. You'd have to be in some pretty serious shit for these templates to reduce mental overload rather than add it.
- zelos 8y agoI think it reduces some mental load because it documents the interface: you don't have to look up which flags are valid for which functions, the types tell you. Plus, with a small amount extra code you can do things like iterate over all the flags that are set etc.
- jstimpfle 8y agoThe best way to iterate and do stuff with enums that I know is this way: enum { FOO_A, FOO_B, FOO_C, NUM_FOOS, }; struct FooInfo { int kind; // FOO_?? const char *str; const char *long; }; static const struct FooInfo fooInfo[NUM_FOOS] = { { FOO_A, "FOO_A", "The A of all the foos" }, { FOO_B, "FOO_B", "The B of all the foos" }, { FOO_C, "FOO_C", "The C of all the foos" }, }; for (int i = 0; i < NUM_FOOS; i++) { printf("Got #%d, %s. Description: %s\n", fooInfo[i].kind, fooInfo[i].str, fooInfo[i].long); } More goodies: // if you want to use them as bitmasks // (but only few enums are used this way) enum { FOO_A_BIT = 1 << FOO_A, FOO_B_BIT = 1 << FOO_B, FOO_C_BIT = 1 << FOO_C, }; // if you want to make strings out of C symbols, you // can also use a macro like this: #define FOOINFO(name, long) { name, #name, long }, static const struct FooInfo fooInfo[NUM_FOOS] = { FOOINFO( FOO_A, "The A of all the foos" ), FOOINFO( FOO_B, "The B of all the foos" ), FOOINFO( FOO_C, "The C of all the foos" ), };
- lomnakkus 8y agoBoth of these suffer from the potential maintenance problem of duplicating the list of enumerated values. You can avoid that by using the X-Macro pattern, but that's quite heavy-handed and tedious to do if you have a lot of different enums. It also doesn't use "enum class" which means that the namespace will be polluted unnecessarily.
- jstimpfle 8y agoI've read about X-Macros, but I don't really like many-line #defines. Another way is to autogenerate the enum definition + value table form from a single table represented as text. But I don't find the duplication to be much of a problem anyway, since mistakes (which are rare enough) don't go undetected for a long time. I don't like namespaces. With namespaces a thing is known under one name here but not somewhere else. I find it really hard - in terms of mental overhead, and it also makes use of crude tools like grep much less effective. I've never had any problems with name collisions, while applying only very little discipline. In my experience it's mostly a theoretical problem. (Btw., namespace names could conflict as well ;-> )
- amag 8y ago> I've never had any problems with name collisions, while applying only very little discipline. Oh boy, you need to apply more than a little discipline. I applied only very little discipline once and defined a macro which I properly namespaced (or so I thought) e.g. ACME_SOMETHING. After quite a bit of debugging I realized that in one compilation unit a variable assigned with ACME_SOMETHING had a different value than it would get in all other compilation units. As it turns out my very little discipline wasn't enough and one of the system headers had a ACME_SOMETHING-define to that other value!
- jstimpfle 8y agoI would say two disagreeing definitions baked in is in the first place a problem with the C compilation process in general. I haven't hit that particular problem you describe, but I've seen xpdf fail in glorious ways because there were two versions of a "GlobalParams" structure. For years bug fixes kept trickling in, "fixing" various unexplainable misbehaviours. At some point someone noticed that it could all be traced back to the problem that various parts of the program were disagreeing what GlobalParams really was. In that case the reason was that xpdf linked against libpoppler, a library that had been forked off xpdf itself. So it was really about two versions of "the same" structure. In your case there might always have been two entirely different things (I don't know?), but anyway I expect a good compilation process two catch those cases such that the worst that could happen is a compilation error.