3

I have a simple C++ class that uses generic templates to store and retrieve generic variables. Storing them is no issue but returning the generic variable returns a hexadecimal value.

Could someone tell me why it's doing that?

node.h

#pragma once
#include <iostream>

template <typename T>
class Node {
    private:
        T data;
        Node *next_node;

    public:
        Node(T data) {
            this->data = data;
            std::cout << "Node with data - " << this->data << " - has been created." << std::endl;
        }
        
        T get_data() {
            return this->data;
        }
        
        void set_next_node(Node next) {
            this->next_node = next;
        }

        Node get_next_node() {
            return this->next_node;
        }
};

main.cpp

#include <iostream>
#include "node.h"

int main() {

    Node node = new Node("Hello World");

    std::cout << "Node data: " << node.get_data() << std::endl;

    return 0;
}

output

gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ g++ main.cpp -o main
gabriel@desktop:/media/gabriel/main/repositories/CPP Sandbox/nodes$ ./main
Node with data - Hello World - has been created.
Node with data - 0x55ec552d3eb0 - has been created.
Node data: 0x55ec552d3eb0


Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
Gabriel Gavrilov
  • 337
  • 3
  • 11

2 Answers2

8

The problem you are facing is that you are using new to create a node but then trying to assign the pointer returned to a non-pointer Node variable.

This line is the problem:

Node node = new Node("Hello World");

What this does is to first construct an unnamed Node object with a template type of const char *; then, by using the pointer to that new object to initialize your node variable, you are constructing a second Node object, with the deduced template type being Node*. The cout lines showing hexadecimal values are correctly displaying the address value stored in that second, named Node variable.

You can get round this in several ways. The easiest is to not use the new operator:

Node node{ "Hello World" }; // Construct object directly

Another way would be to continue using the new call but then make your node a pointer:

int main() 
{
    Node<const char*>* node = new Node("Hello World"); // Or auto node = new Node("Hello World");
    std::cout << "Node data: " << node->get_data() << std::endl; // Now we need "->" instead of the "."
    delete node;
    return 0;
}

The first line of code in your main function is, effectively, doing this:

Node node{ new Node("Hello World") };

Thus creating two nodes with the named one having it's template type as Node<const char*>*. Or, to put it another way, your first line is equivalent to the following, with explicit template types:

Node< Node<const char*>* > node = new Node<const char*>("Hello World");

Also note that the = operator here is not an assignment but an initialization; this is why the constructor is called.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
7

Without CTAD (class template argument deduction) the line in main reads like this:

Node<Node<const char*>*> node = new Node<const char*>("Hello World");

I am not sure what you actually wanted, but I am certain that it isn't this.

The address that is printed is value of the Node<const char*>* member of the Node<Node<const char*>*>.


Be warned, what follows is bad taste. It is a joke. If you do not get the joke, forget that you have seen the code. Don't do this at home. Or at work. Or really anywhere. Not. In c++. Please. Ok, lets do it.

I removed some cruft from OPs code and also the string literal to avoid possible confusion about conversions or array to pointer decay. Now, this will produce the expected output of 42:

#include <iostream>

template <typename T>
struct Node {
    T data;
    Node(T data) : data(data) {}
    Node(Node<T>* other) : data(other->data) { delete other; }
};

int main() {
    Node node = new Node(42);
    std::cout << "Node data: " << node.data << std::endl;
}
Jeff Schaller
  • 2,352
  • 5
  • 23
  • 38
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185