Class Pointers to itself

How would I write the code that would make a pointer to a pair that contains any type as its .first and a pointer to itself as its .second

 
pair<int, ptr to pair<pair<int, ptr to pair<>> *> *> * ptr;
Last edited on
Does it have to be a pair?
1
2
3
4
5
template <typename T>
struct Node {
  T first;
  Node<T>* second {nullptr};
};
As far as I'm aware, the type system by itself isn't enough to enforce what exactly something is pointing to, only that it is pointing to a particular type.

If we think about something like a linked list, technically you could have a node that points to itself, there's no way to prevent that just from the type system itself. What you do instead is have a wrapper around Nodes (like a LinkedList class that contains the pointer to the head node), and in using this wrapper, you could restrict the behavior to your liking (e.g. forcing a pair to contain a pointer to itself, for whatever reason).

If the purpose of this question is just for sheer knowledge, ask away. But if this question is asked for some practical purpose in mind, it might better to describe what you're actually trying to achieve.

Edit: For example, in keskiverto's example, you can enforce the rule (at runtime) by the constructor acting as a wrapper.
1
2
3
4
5
6
7
8
9
10
template <typename T>
struct Node {
  public:
    Node(T value)
    : first(value), second(this) { }
    T first;
    
  private:
    Node<T>* second {nullptr};
};
Last edited on
Thanks, all I could see was kinda the same thing as lining up to mirrors: a picture in a picture in a picture going on forever and I kinda just died.
I’d say it’s with a purpose, but in the end it’s basically just to further my knowledge. It’s still took me a while to fully align what your codes did because I was looking at my pointers wrong.

So just going to repeat how this works because it’s still a tad bit shaky..

As struct(Node) or class can hold a pointer of itself so we make whatever other values with the template(.first) and then make a pointer too ourselves and since we do not have to pass the type of pointer we want it doesn’t create the previously mentioned mirror type problem that makes my brain explode and can point it to our selves or as I should have more clearly stated, other objects of the same exact type/class.

The pointer in node works because pointers aren’t an actual class and no mirror stuff happens because the pointer type doesn’t need to be passed.
a pointer to itself as its .second

From a design standpoint, I have to wonder why.

1
2
3
int a{ 5 };

int * toItSelf = &a;


I mean, why?

1
2
3
std::pair< int, double > i{ 5, 5.5 };

auto p = &i;


No doubt you noticed the infinite self reference the declaration you've requested implies, but the point I'm making is that if you did make the thing, it would have it's own address available anyway, as it does in the previous pair example.

There's just no real useful purpose other than trying to figure out how.

One way is something like this:


1
2
3
4
5
6
7
8
std::pair< int, std::any > i{ 5, nullptr };

i.second = &i;

auto p = i.second;

auto x = any_cast< std::pair< int, std::any > *>(p)->first;


Not that it's pretty, and this is just illustration of the idea to use std::any to break the infinite declaration cycle.

But.......why?

In the above example, this is true:

any_cast< std::pair< int, std::any > * >( i.second ) == &i;

...so, you don't need to ask for it....

Last edited on
@Niccolo, he meant a pointer to the same type, not necessarily a pointer to itself. He seems to be thinking of using it as a linked list node.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <utility>

template<typename T>
std::pair<T, void*>* make(T n, void* p=nullptr) {
    return new std::pair<T, void*>(n, p);
}

template<typename T>
std::pair<T, void*>* second(std::pair<T, void*>* p) {
    return (std::pair<T, void*>*)(p->second);
}

int main() {
    auto list = make(1, make(2, make(3, make(4, make(5)))));    
    for (auto p = list; p; p = second(p))
        std::cout << p->first << '\n';
}

Last edited on
Well, now he says that, but not until 3 minutes before I posted my answer....up to that moment, he was saying "pointer to itself"....the clarification was otherwise just not there.

BTW, std::any is the modern void *, but it does require C++17
pointers can be set to nothing.
it does not go on forever (partly because ram in finite, as are all things in your computer) because you can break the chain. A picture is worth a LOT of words they say, and an animation can be even better. I highly recommend you look at a linked list animation online somewhere.
but in short

1 -> 2 -> 3 ->|
so you have a node with some data, here, the integer 1. its pointer points to another node. That node has data of 2, and a pointer to another node. The third has a data value of 3, but the pointer does not point anywhere (it has the special value of 0 or nullptr or null depending on who wrote the code and when). Because it has this special value, and because you are a great programmer who checked your pointer for that value before trying to use it, you know to stop there. You can now come along and add to the front easily: get a new node, and set the pointer to the 1, and it links up nicely. You can insert into the middle or end as well with some additional work (the front is the easy one).

I wonder... could I use a macro to create the mirror affect thing? Could I make a recursive macro func?

 
#define mirror(a<t,REPLACE>) a<t,mirror(a<t,a>)> 


Obviously a horrible idea but kinda funny
Last edited on
@Niccolo yeah I know the feeling, the last thread I made I had to write all might code on the spot directly into the message box so I kept missing posts.
@dutch yeah basically

Also, holy crap dude how long did that take you? A minute?
Last edited on
Don’t worry I’m not going anywhere near recursive macros anytime soon, it was purely speculation.
Topic archived. No new replies allowed.