0

Spoiler-Alert: I forgot the * in the header file, it compiled but ignored my operator overload, and just printed the adress.

Leading to this confused mess of a question, i'm so sorry! Thank you all!

I've included a simple example of what i want to do. I have a pointer to a class, and i need to output it using <<, WITHOUT copying the value first.

I implemented an operator<< function that takes a reference as an argument. This has been suggested in several answers on StackOverflow as well -

However, i can't get the compiler to actually pick my overloaded operator function.

When i run the example below, it simply returns 0x6af59ffac0 (because the standard << implementation for pointers is used)

Granted, you could always dereference the pointer and write a pass-by-value operator<< function. But in my case this is not alllowed, as no other instance of the class should be created on the stack. (Basically trying to achive this without copying the class)

So, at this point i am probably going to simply avoid the << operator in that specific case, and write my own function. (see the workaround at the bottom) But i can't help being frustrated at this. Surely, there should be a way to hint to the compiler which version of the operator to use? (Similar to rust's Turbofish Operator ::<>)

Or is this legitimately impossible?

Example::

#include <iostream>
using namespace std;

class TEST {
    public:
        string name;
        int id;
        TEST(string nname, int iid) : name(nname), id(iid) {}
};



std::ostream& operator<<(std::ostream& out, TEST &m) {
    return out << "Test Output, class has values: ID" << m.id << "; NAME: " << m.name;
}

int main() {
    TEST var("tester", 22);
    cout << &var; // Just prints the memory location
    cout << (TEST*) &var; // Still just prints the memory location

    return 0;
}

What i would do to avoid the language limitation (in case noone has an answer): (this works for me since a method doesn't have a copy of its class in its stack frame, just a pointer)

#include <iostream>
using namespace std;

class TEST {
    public:
        string name;
        int id;
        TEST(string nname, int iid) : name(nname), id(iid) {}

    std::ostream& display(std::ostream& out) {
        return out << "Test Output, class has values: ID" << this->id << "; NAME: " << this->name;
    }
};

std::ostream& operator<<(std::ostream& out, TEST m) {
    return m.display(out);
}

int main() {
    TEST var("tester", 22);
    var.display(cout);

    return 0;
}
  • 2
    `std::cout << var;` There's nothing confusing about this. You are explicitly printing the address, and not the object. Your `operator<<()` should also take the `TEST` parameter as a reference to `const`. – sweenish Oct 11 '22 at 11:50
  • Your `operator<<` should get `TEST * m` (pointer) if you want to pass an address. – wohlstad Oct 11 '22 at 11:51
  • If you have a pointer to the object, you can output it using `std::cout << *ptr;` – Eljay Oct 11 '22 at 11:59

2 Answers2

0

Remember that when declaring variables, including arguments, the & means reference, not pointer.

That means you need to pass (use) an actual object instance to be referenced:

std::cout << var << '\n';
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
0

I have a pointer to a class, and i need to output it using <<, WITHOUT copying the value first.

You wrote

std::ostream& operator<<(std::ostream& out, TEST &m)

which takes a reference to a TEST object and doesn't copy anything. Why did you think it would copy something?

Anyway, that stream insertion operation probably should be

std::ostream& operator<<(std::ostream& out, TEST const &m)

(since it shouldn't be changing the object it prints).

However, i can't get the compiler to actually pick my overloaded operator function.

Well, you wrote an overload that takes a reference argument. You have to pass a reference, because that's the type you wrote. To get one that takes a pointer ... just write one that takes a pointer argument instead

std::ostream& operator<<(std::ostream& out, TEST const *m)
{
  return out << "TEST* : ID" << m->id << "; NAME: " << m->name;
}

Note that the default ostream& operator<<(ostream&, void*) is always a worse match than any specific non-void pointer overload. It just fell back on that because it was the only match available.


Just to clarify again

Granted, you could always dereference the pointer and write a pass-by-value operator<< function

nobody has suggested a pass-by-value operator<<, and that isn't what you originally wrote. You did add a pass-by-value version in your second code block but, since the first version was pass-by-reference, I don't know why. If you don't know how to read basic syntax like &, * and ->, this would be an excellent time to read a good book.

Useless
  • 64,155
  • 6
  • 88
  • 132
  • OH MY GOD! I could've sworn i tried that before, before i made my simplyified version, and it didn't work! And you know what? I did try it!! But i forgot to change the header file! Header File: `std::ostream& operator<<(std::ostream& out, TEST m);` Source File: `std::ostream& operator<<(std::ostream& out, TEST *m) {` There was no compiler error, no linker error, but the compiler picked the `ostream& operator<<(ostream&, void*)` implementation!! I wasted so much time on this ahhhhhhhhhh Thank you so much!! – Darksilvian Oct 11 '22 at 14:27