namespace A
{
class B
{
public:
B(int);
};
}
namespace C
{
class D
{
static const ::A::B b;
};
}
const ::A::B ::C::D::b(0); // #1
// const ::A::B C::D::b(0); // #2
// const ::A::B (::C::D::b)(0); // #3
Option #1 fails to compile. Now that I’ve thought about it for a while, I’m pretty sure the compiler considers the whitespace between “B” and “::C” insignificant, so it is trying to find a member “C” inside “B”. If that’s what’s happening, I need some way to convince the compiler that these are two separate qualified names.
Options #2 and #3 both seem to work in a very minimal test. #3 seems somewhat less vulnerable to name collisions since it’s more qualified. #3 is also somewhat easier for me to switch to. So I lean towards #3, but it looks weird.
Is there any strong reason to prefer one over the other? Can I expect both to work correctly on other compilers? Is there an even better solution than either one? And for that matter, am I correct about why #1 fails?
Probably unnecessary details
- The code that inspired this question was output by a source code generator I wrote. The identifiers are derived from the generator’s input, so I’m concerned about name collisions, specifically unintentional shadowing between scopes, which the generator can’t detect. So, I wrote the generator to qualify every identifier as fully as possible.
- I’m compiling on VC2010.
- I’m intentionally not using C++0X features, as I want the code to be portable to certain older compilers.
- The specific compiler error is “error C3083: ‘C’: the symbol to the left of a ‘::’ must be a type”
That’s precisely correct.
Option #3 looks fine to me (and is compliant); that is, if you’re really stuck with this rather silly-looking requirement. 🙂
I use it myself to conclude a blog post on a very similar “issue”.