4 ms·
Both 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
by lomnakkus 8y ago
Both 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.
- dkersten 8y ago> I don't like namespaces. With namespaces a thing is known under one name here but not somewhere else. I like namespaces for this exact reason. Basically, never ever use "using namespace foo" or namespace aliasing and always fully qualify your symbols "foo::bar". Now I always know where something is coming from. > it also makes use of crude tools like grep much less effective. It also makes grepping much simpler. For example, I can grep a file for "std::" to find all standard library symbols used. As a side benefit, while I said above never to use namespace aliasing, I did recently come across a situation where it was actually beneficial. The code in question was using std:: containers, but it would have been nice to be able to optionally use EASTL containers instead (which are mostly drop-in replacements with different performance characteristics). One simple way to do this would be to use a different namespace in place of std:: (I'm gonna just say foo:: for this example) and then do something like this: #ifdef USE_EASTL namespace foo = eastl; #include <eastl headers> #else namespace foo = std; #include <std headers> #endif > (Btw., namespace names could conflict as well ;-> ) Sure, but they can be aliased.
- jstimpfle 8y ago> never ever use "using namespace foo" or namespace aliasing and always fully qualify your symbols "foo::bar". Now I always know where something is coming from. That's why I think they are silly. At this point, nothing gained vs simple prefixes. ONLY lost the ease of certainty that what you say actually holds true. And in fact, on the implementation side it usually doesn't hold true - I've rarely seen a namespaced implementation that uses full qualification. Moreover "std::" is one character more, and a lot more noise, than "std_". Moreover in other common namespace syntaxes (like "std.") you still have the disadvantage that the namespace really is a separate lexical name (you could also write "std . foo" - it's logically, but not lexically, the same thing as "std.foo"). In conclusion, it's just a lot of unnecessary complexity. A complex solution looking for a problem. > It also makes grepping much simpler. For example, I can grep a file for "std::" With properly prefixed symbols you can do that as well. And more generally, you compile a list of symbols to grep for, or use other patterns (like std::.* tty .* or whatever) that likely don't match such an artificial namespace exactly. (In other words, namespaces are another opportunity for an implementor to get paralysed by choices he has to make, and another opportunity to be overly presupposing of how its API should be used by callers). > As a side benefit, ... Yeah I know I'm sounding a bit snarky now, but that's what linkers were invented for.
- ufo 8y agoDo enums change often enough for this to be a problem though? Often just adding a comment reminding to keep the enums in sync is enough.
- lomnakkus 8y agoObviously it depends on the particulars of any given project, but if you're deriving more than just the string names of the enum values it may be worth it. Using X-macros can sometimes reduce boilerplate hugely simply through avoiding switch statements on the enum values.
- tom_ 8y agoI think "often" is an exaggeration, but even if it did work that regularly, what about the times it doesn't? Meanwhile, you're sat in front of a computer. Its entire job is to keep on top of stuff like this. Why not use it?
- jstimpfle 8y agoBecause it's harder to do it in a complicated formal way than simply do it in the most straightforward way. If a type of mistake happens only very rarely and is typically easy to detect, it's almost certainly not a good idea to worry about it. You pay each time you express something using the more complicated formalism, and each time you work on parts that somehow have to deal with the more complicated artifact, and only every Nth time there is a marginal gain from using it.
- tom_ 8y agoIn the abstract, sure - it's not uncommon for projects to start to become consumed by their own infrastructure. But I've never seen X-macro enum stuff contribute to that. (This does of course presuppose that you really want to be able to always get the string name of an enum values. I've found this to be reliably the case, if only for logging purposes, but I've only got my own experience to go on.)