Why Does Everybody Use Unanchored Namespace Declarations (I.E. Std:: Not ::Std::)

Why does everybody use unanchored namespace declarations (i.e. std:: not ::std::)?

The practical reason for unanchored namespaces is that one level of namespaces usually is enough. When it isn't, a second level is usually going to be used for implementation details. And finally, even when using multiple levels, they are still usually specified implicitly from root level. ie. even inside namespace ns1, you'd typically refer to ns1::ns2::foo instead of ns2::foo or ::ns1::ns2::foo.

So, for these three reasons the ::ns1 form is redundant in normal cases. The only case where I'd consider it would be in submissions to Boost, because as a Boost author I won't know where my software will be used.

Is it legal C++ to declare a nested namespace `std`?

In the reserved names standard 17.4.3.1 (and its sub-paragraphs) I can't find anything that prohibits using std as a nested namespace name. It's not a macro, it's not in the global namespace, and it doesn't seem to meet any of the "external linkage criteria" that would prohibit it.

It appears to be legal (although as you note extremely inadvisable).

C++: Namespace syntax question

It will work if you put in the ; after the class definitions. But it will not work in quite the way you expect. First, it tries to figure out what namespace you're talking about. First it will looks for ::Stuff::Stuff, and when it doesn't find it, it then looks for the namespace ::Stuff. It finds that namespace, so it then looks in that namespace for Sprite and finds your class.

If you have an unanchored namespace, it looks for that namespace path in the current namespace, then in the enclosing namespace, then in the enclosing enclosing namespace... etc... until it gets to the top level namespace.

See this question of mine:

  • Why does everybody use unanchored namespace declarations (i.e. std:: not ::std::)?

In my opinion, people ought to be a lot more careful than they are about referring to namespaces. Hardly anybody ever uses a root anchored namespace specification, even when they should be because they really do mean a specific absolute namespace and not a name relative to the current namespace.

Here are a couple of interesting cases:

 1 namespace Bar {
2
3 class A {
4 };
5
6 } // end namespace ::Bar
7
8 namespace Foo {
9
10 class A {
11 };
12
13 Foo::A joe; // Refers to the A declared on line 10
14
15 namespace Foo {
16 }
17
18 Foo::A fred; // Error, finds ::Foo::Foo and doesn't find A there.
19 ::Foo::A fred; // Works and refers to the A declared on line 10
20
21 Bar::A barney; // Works, and refers to the A declared on line 3
22
23 namespace Bar {
24
25 class A {
26 };
27
28 } // end namespace ::Foo::Bar
29
30 Bar::A wilma; // Works, and refers to the A declared on line 25
31 ::Bar::A betty; // Also works, and refers to the A declared on line 3
32 ::Foo::Bar::A dino; // Also works, and refers to the A declared on line 25
33 } // end namespace ::Foo

When, where and why use namespace when registering custom types for Qt

I'm referring to Qt5 in this answer. Qt4 doesn't go well with this use case.

Data stream operators

Data stream operators are not required for your type if you only intend to use it in signals and slots. They are required if you want to do some serialization.

Pointers, references and values

Qt considers MyClass and MyClass* two different unrelated types. You should declare, register and use them separately. Using const MyClass & argument type is compatible with MyClass in Qt meta-object system. Note that using MyClass and MyClass* meta types simultaneously in one program is unusual and can cause mistakes and confusion. You should choose one of the options and use it throughout the program. Also passing pointers to slots is not recommended because it causes unsolvable ownership problem. So I recommend to use passing by const reference (which sometimes will be converted to passing by value internally in Qt signal-slot system). If MyClass objects contain massive data, you should implement implicit data sharing using QSharedDataPointer.

Declaring a meta type

First of all, you always need to declare your meta type:

Q_DECLARE_METATYPE(foo::MyClass)

It works at compile time, so there are no limitations on how you refer to your class. The following code will work as well:

using namespace foo;
Q_DECLARE_METATYPE(MyClass)

Registering a meta type

Now you need to register your classes. Theoretically, you need to specify all strings that you want to use to refer to your type, i.e.:

qRegisterMetaType<foo::MyClass>("MyClass");
qRegisterMetaType<foo::MyClass>("foo::MyClass");

It doesn't matter how you refer to MyClass in the template argument. The following code will work similarly:

using namespace foo;
qRegisterMetaType<MyClass>("MyClass");
qRegisterMetaType<MyClass>("foo::MyClass");

For example, the "MyClass" and "foo::MyClass" strings are used to identify argument types when you refer to your signals and slots like SIGNAL(signal1(MyClass)).

New signal and slot syntax

If you using new signal slot syntax with pointers to member functions, you need to do only one registration with arbitrary string argument. It seems that it is intended to make it work even without any registrations. This part of the docs instructs to only add Q_DECLARE_METATYPE, in opposite to this that requires qRegisterMetaType(). Unfortunately, now in my Qt installation it works only with direct connections. Queued connections still require at least one registration call.

Implicit registration of class without namespace

I was experimenting with some variants of registration in Qt 5.1 and found out that Qt automatically registers aliases without namespace. So if you write

qRegisterMetaType<foo::MyClass>("foo::MyClass");

, Qt will additionally automatically register "MyClass" alias. So, after executing this statement you will be able to refer to your type as MyClass and foo::MyClass. There is no information in the documentation about how Qt handles namespaces. We could assume that this behavior is intended and will not be removed in next versions but I wouldn't rely on that. The following code makes implicit registration obvious:

qRegisterMetaType<foo::MyClass>("foo::MyClass");
qRegisterMetaType<bar::MyClass>("MyClass");

Qt 5.1 says:

QMetaType::registerTypedef: Binary compatibility break -- Type name 'MyClass' previously registered as typedef of 'MyClass' [1030], now registering as typedef of 'bar::MyClass' [1032].

Qt 4.8 works without error (it seems that this behavior is not yet introduced in this version).

Why does import need the project name and not just the object?

It's because your project has a root namespace - you can see this in your project properties. You can delete this in the project properties - this will result in allowing you to simply use the class name from another project. However, namespaces are a good way to organize your classes. In VB, the project defaults to having a root namespace, which you don't see in your code files.

Within your project, since it seems to be all within the same root namespace, you don't have to qualify with the root namespace for code within the root namespace. The "Imports" statements are not within a namespace (only types can be within namespaces) - that's why you have to provide the full qualification there.



Related Topics



Leave a reply



Submit