| > Solved by C++ namespaces. I've never understood what's the practical difference between NS::foo() and NS_foo() with regards to preventing name collisions. Can someone enlighten me? I know some disadvantages of the namespacing variant, though. There are now multiple names for the items defined in the namespace: the qualified one and the unqualified one. The latter is often not unique in practice, since the programmer relies on the qualified name for uniqueness. In effect, making simple text searches for identifiers is very unreliable. Note I do use IDEs, but I also code in vim, and I need to do simple text searches even when working in Visual Studio. Additionally, there's no guarantee that there are no spaces around the scoper. I believe "NS :: foo" is just as valid, which makes me uneasy with regards to text search, as well. Another issue I have: $ cat test.cpp
namespace NS { int foo() { return 0; } };
$ g++ -c -o test.o test.cpp
$ nm test.o
0000000000000000 T _ZN2NS3fooEv # I hate my life
> Modern C++ has strongly-typed scoped enums for such constants.I haven't found those working for me. Apart from the namespacing issue described above, I have issues with explicit enum types. One issue is that I often need to put sentinel / "missing" values (typically the value is -1) where an enum value is expected. Even more often, I want to iterate over the values of an enum. C++'s enum "type safety" makes working like this really unergonomic. The way I go about this is I don't even use names for my enum types, and I fully qualify the enumeration values. enum {
FPGAPARAM_BLA,
FPGAPARAM_BLUB,
FPGAPARAM_FOO,
NUM_FPGAPARAM_KINDS
};
struct ASDF {
int fpgaparamKind; // obvious what kind of values are expected here...
};
for (int i = 0; i < NUM_FPGAPARAM_KINDS; i++) {
struct ASDF asdf;
asdf.fpgaParamKind = i;
do_asdf(&asdf);
}
In programming, the slightest mistakes, like putting a "-" instead of a "+", result in program bugs. These mistakes are much more likely to be made (and much harder to spot) than mistakes involving enum values from the wrong set. I won't let programming ergonomics be ruined in the name of "type safety". |
They both do the job. There’re 2 practical differences.
1. You can write `using namespace` inside functions or the whole .cpp files. This often makes the consuming code more readable.
2. Sometimes you want to replace implementations. With prefixes it gonna be massive changes likely to introduce new bugs. With namespaces, replace `using std::vector` with `using eastl::vector` and you’re done.
> Even more often, I want to iterate over the values of an enum.
I only need to do that rarely. When I do, I cast types like this:
> I won't let programming ergonomics be ruined in the name of "type safety".I disagree on ergonomics. VS makes much easier to consume API with strongly typed enums: ePar<Ctrl+Space>::f<Enter>, to type eParamKind::Foo It’s similar with namespaces versus prefixes BTW, IDE will first auto-complete the namespace, then only list members of that namespace once you type the `::`
Update: another C++ feature relevant for game development is overloaded operators. Games often do non-trivial amount of math on small vectors, matrices and quaternions. Overloaded operators make sense for them.