Home > Back-end >  Is there a way to pass a &CustomType or *CustomType into the "Stream Insertion" Operator?
Is there a way to pass a &CustomType or *CustomType into the "Stream Insertion" Operator?

Time:10-12

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;
}

CodePudding user response:

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.

CodePudding user response:

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';
  • Related