Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't we declare a namespace within a class?

Declaring a class within a class is valid. (Nested classes)

Declaring a namespace within a class is invalid.

The question is: is there any good reason (other than c++ grammar/syntax problems) to forbid the declaration of a namespace within a class ?


As for why would i want to do that, here is an exemple :

Let's have a basic delcaration of a binary tree container

template<typename Data> class binary_tree {  public:   ... stuff ....        private:   ... iterators class declaration ...   public:   typedef left_depth_iterator_impl     left_depth_iterator;   typedef right_depth_iterator_impl    right_depth_iterator;   typedef left_breadth_iterator_impl   left_breadth_iterator;   typedef right_breadth_iterator_impl  right_breadth_iterator;    ... stuff ....        private:   Data         data;   binary_tree* left;   binary_tree* right; }; 

Now i notice that there are a lot of iterators in my class, so i would like to regroup them within the same namespace like this :

template<typename Data> class binary_tree {  public:   ... stuff ....        private:   ... iterators class declaration ...   public:   namespace iterator   {     typedef left_depth_iterator_impl     left_depth;     typedef right_depth_iterator_impl    right_depth;     typedef left_breadth_iterator_impl   left_breadth;     typedef right_breadth_iterator_impl  right_breadth;   }    ... stuff ....        private:   Data         data;   binary_tree* left;   binary_tree* right; }; 

This would allow a simple usage :

void  function() {   binary_tree::iterator::left_depth   it;    ...stuff... } 

This works if i use a class instead of a namespace, but i am then forced to declare a class that will never be instantiated which is quite a namespace.

Why allow nested classes and forbid nested namespaces within classes ? is it a legacy burden ?


Answers with semantic reasons that do not only quote part of the standard(especially syntax parts) will be apreciated :)

like image 959
Drax Avatar asked Nov 21 '12 00:11

Drax


People also ask

Can you declare a namespace in a class?

Declaring a namespace within a class is invalid.

How do you declare a namespace?

Typically, you declare a namespace in a header file. If your function implementations are in a separate file, then qualify the function names, as in this example. A namespace can be declared in multiple blocks in a single file, and in multiple files.

Can a namespace have the same name as a class?

Inside a namespace, no two classes can have the same name.

What is the main purpose of the namespace?

Namespaces provide a way of declaring variables within a program that have similar names​. It allows users to define functions with the same name as a function in a pre-defined library or used-defined functions within main() . Namespaces can also be used to define classes, variable names, and functions.


2 Answers

Since you asked which parts of the standard mandate namespace location, we hit that up first:

C++11 7.3-p4: Every namespace-definition shall appear in the global scope or in a namespace scope (3.3.6).

Regarding class definitions and the proposition of declaring a namespace within, I bring you to...

C++11 9.2-p2: A class is considered a completely-defined object type (3.9) (or complete type) at the closing } of the class-specifier. Within the class member-specification, the class is regarded as complete within function bodies, default arguments, exception-specifications, and brace-or-equal-initializers for non-static data members (including such things in nested classes). Otherwise it is regarded as incomplete within its own class member-specification.

Ergo, a class definition is finite once the closing curly is reached. It cannot be opened back up and extended (derivation is something different, but it is NOT extending the class just defined).

But lurking at the very beginning of the standard definition of a namespace is the ability to extend it; to expand it for lack of a better term:

C++ 7.3-p1: A namespace is an optionally-named declarative region. The name of a namespace can be used to access entities declared in that namespace; that is, the members of the namespace. Unlike other declarative regions, the definition of a namespace can be split over several parts of one or more translation units. (emphasis added).

Therefore, a namespace within a class would violate the definition in 7.3-p4. Assuming that was not present, it would be possible to declare a namespace anywhere, including in a class, but since the definition of a class is formalized once it is closed, you would be left with only the ability to do the following if you maintained compliance with 7.3-p1:

class Foo {    namespace bar    {        ..stuff..    }     .. more stuff ..     namespace bar    {        ..still more stuff..    } }; 

The usefulness of this feature was likely debated for about 3-full-seconds before 7.3-p4 was established to settle it.

like image 194
WhozCraig Avatar answered Sep 25 '22 09:09

WhozCraig


I'm going to disagree with others here. I wouldn't say there's no real advantage. Sometimes I'd just like to segregate code without extra implications. As an example, I was working in a multithreaded ringbuffer module and wanted to split the state members, some of which are atomic and/or memory-aligned, into namespaces for the producer and the consumer.

By just naming everything with producer or consumer prefixes (which is my current annoying implementation), I'm adding pollution that makes code harder to read. E.g. when everything owned by the producer starts with producer, it's easier for your brain when reading it to accidentally autocorrect producerProducerTimer (producer copy of a producer timer) as producerConsumerTimer (producer shadow of a consumer timer) or consumerProducerTimer (consumer shadow of a producer timer). Debugging that takes way longer than it needs to because the code is no longer skimmable.

By creating a nested class/struct:

  • I could be giving the next developer who maintains this code the idea that more than one of these could/should be instantiated, copied, and assigned to one another within a context, so now instead of just worrying about naming I also have to = delete these things.
  • I could be adding memory footprint to the context with structural alignment padding that might not otherwise be necessary.
  • Making all members static isn't an option, since more than one context can be instantiated that will need its own producer/consumer state variables.
  • Functions of such a struct no longer have access to other member data or functions, such as constants or functions that are shared by both sides, but instead have to take these things as arguments.

Ideally, I'd like to be able to change things like this:

rbptr producerPosition; rbptr consumerPosition; 

to this:

namespace producer {     rbptr position; } namespace consumer {     rbptr position; } 

Then, functions that should only touch consumer members can use the consumer namespace, functions that should only touch the producer members can use the producer namespace, and functions that need to touch both have to explicitly qualify them. There'd be no way to accidentally touch a consumer variable in a function that's only using the producer namespace.

In this case, the desire is purely for reducing naming collisions between producer and consumer copies of things, and reducing naming collisions are what namespaces exist for. For that reason, I support the proposal to be able to declare namespaces inside classes.

like image 37
ErsatzStoat Avatar answered Sep 23 '22 09:09

ErsatzStoat