Shorter scope resolutions for private nested classes
Asked Answered
G

3

6

I have this (simplified) situation:

class Tree {
    class Iterator {
        class Stack {
            // ...
        }
    public:
        // ...
    }
public:
    //...
}

I don't want to clutter the classes' definitions and I decide to write only method declarations inside classes themselves. Later on (waaay down below) when I want to define, say, copy assignment operator like this:

Tree::Iterator::Stack& Tree::Iterator::Stack::operator = (const Stack& p_stack) {
// ...
}

I have to deal with these nasty scope resolutions. I'm wondering if there's a way to shorten them, because using and typedef, as I know them, don't offer me anything.

EDIT: Since this is not CodeReview, and @Yulian requested clarification, here's the short version:

I'm making an iterative Red-Black Tree implementation. Mentioned class Iterator is for post-order traversing (so it's post-order-specific), and class Stack is its utility class. In this short program, only class Tree uses the Iterator, and only Iterator uses Stack.

After @Yulian's reminder, I recalled that it would be way more object-oriented if the mentioned classes were separately defined (maybe even as templates), but this is a small, self contained program and I'm trying to keep it that way.

EDIT: Self-contained also means that it's an isolated, single-file program, so no .h files or external code re-using whatsoever. Why? Because ACADEMIA (and associated arbitrary restrictions).

Graehme answered 12/11, 2015 at 20:45 Comment(9)
Why doesn't using and typedef buy you anything?Marcellusmarcelo
They are private classes, so I can't just say using Stack = Tree::Iterator::Stack; or something similar - Iterator and Stack are inaccessible.Dicast
You could declare the nested class and then define its member functions in line, when you define the class later on. But, I think that code looks fine on its own. If you also have a bunch of namespaces to deal inside the function definitions, you can actually put using declarations inside each function definition.Pinsk
How does not nesting the classes make it any less small and self-contained? It's probably about the same amount of code as you have already, just laid out differently.Pinsk
@GuyGreer Yeees, but I'd rather not put this prntscr.com/922zx9 inside the definitions, if you see my point.Dicast
@StefanStanković Sorry, was that directed at the first or second comment? If it's directed at the first (which I'm going to assume), then I understand but still don't really see your original problem as much of a problem at all. These long names don't really clutter up the code much...Pinsk
@GuyGreer On the second remark: True, it doesn't really, but I somehow only want the Tree public interface to be directily accessible.Dicast
To make only the Tree class accessible look up the pimpl idiom.Pinsk
Let us continue this discussion in chat.Dicast
G
3

You could totally eliminate scopes resolutions with a using or typedef. But not with the traditional way because your nested classes are declared private. So you would have to use additional using in the public section of each nested class to "expose" them. Unfortunately, this breaks the "privateness" of them:

class Tree {
    class Iterator {
        class Stack {
            Stack& operator = (const Stack& p_stack);
        };
    public:
      using Stack_Out = Stack;

        // ...
    };
public:
    using Iterator_Out = Iterator::Stack_Out;
    //...

};

using Stack = Tree::Iterator_Out;

Stack& Stack::operator = (const Stack& p_stack) {
// ...
}

LIVE DEMO

You could however, remove scope levels (except for the outer one, i.e., Tree::) with out exposing the private nested classes in the following way:

class Tree {
    class Iterator {
        friend class Tree;
        ^^^^^^^^^^^^^^^^^^
        class Stack {
            Stack operator = (const Stack& p_stack);
        };
    public:

        // ...
    };

    using Stack = Iterator::Stack;
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

public:

}; 

Tree::Stack Tree::Stack::operator = (const Stack& p_stack) {
^^^^^^^^^^^ ^^^^^^^^^^^
}

LIVE DEMO

Grew answered 12/11, 2015 at 21:6 Comment(5)
Nested classes are only private if they are declared in a private section.Jagged
Doesn't this undermine the whole point of having the classes be private in the first place?Pinsk
@Jagged in the OP they are defined in the private section.Grew
Yes. You should insert the missing "your ... declared".Jagged
@GuyGreer yes it does unfortunately.Grew
C
0

First of all it is good to explain what you would like to achieve and way you think this method is good for your task. IMHO, better approach is to create individual classes that are not nested and use them inside the Three class. This approach is called "HAS A". It is more clean easy to maintain and understand from others. If you provide more details we can come up with better class design.

Celestecelestia answered 12/11, 2015 at 21:2 Comment(1)
Thanks, I've clarified the context now.Dicast
S
-2

You can let the preprocessor help you:

#define foobar Tree::Iterator::Stack    
foobar& foobar::operator = (const Stack& p_stack) {
    // ...
}
Sow answered 12/11, 2015 at 21:31 Comment(2)
As I was criticized here, preprocessor definitions polute the world when used needlessly.Dicast
absolutely never do this.Carminacarminative

© 2022 - 2024 — McMap. All rights reserved.