111

myclass is a C++ class written by me and when I write:

myclass x;
cout << x;

How do I output 10 or 20.2, like an integer or a float value?

Shades
  • 667
  • 1
  • 7
  • 22
ali
  • 1,111
  • 2
  • 7
  • 3

5 Answers5

127

Typically by overloading operator<< for your class:

struct myclass { 
    int i;
};

std::ostream &operator<<(std::ostream &os, myclass const &m) { 
    return os << m.i;
}

int main() { 
    myclass x(10);

    std::cout << x;
    return 0;
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • This would output the constructor value `10`? – IgorGanapolsky Jun 27 '16 at 14:15
  • 14
    Note that if `myclass` has any `private` fields, and you want `operator<<()` to output them, `myclass` should declare `std::ostream& operator<<(std::ostream&, myclass const&)` as a friend. – Justin Time - Reinstate Monica Jan 28 '17 at 18:28
  • 3
    Shouldn't this be `const myclass &m` instead of `myclass const &m`? – Nubcake Aug 15 '17 at 21:06
  • 4
    @Nubcake: No. As far as the compiler cares, the two mean the same thing, but I'd still consider the prefix form wrong. To read a C++ declaration, you start from what's being declared, and work your way outward, with `const` after the type, it says: `m is a reference to a const myclass`. With it before the type, it says "m is a reference to a myclass const`, which is right on the ragged edge between meaningless and truly ungrammatical. – Jerry Coffin May 18 '18 at 14:49
  • 2
    For anyone as confused as me, put the operator overloading *outside* of your class definition (just like in the example). – umnikos Nov 07 '19 at 10:08
  • i tried adding this function to my class but it didn't allow me except by defining it as a friend, is this not meant to be a function inside of a class ? – Lorenzo Nov 05 '20 at 04:26
  • 1
    @Lorenzo: No, it can't be a member function. See https://stackoverflow.com/a/9814453/179910 for more details. – Jerry Coffin Nov 05 '20 at 16:29
29

You need to overload the << operator,

std::ostream& operator<<(std::ostream& os, const myclass& obj)
{
      os << obj.somevalue;
      return os;
}

Then when you do cout << x (where x is of type myclass in your case), it would output whatever you've told it to in the method. In the case of the example above it would be the x.somevalue member.

If the type of the member can't be added directly to an ostream, then you would need to overload the << operator for that type also, using the same method as above.

Rich Adams
  • 26,096
  • 4
  • 39
  • 62
  • 1
    Sorry, yes you're right. That's just what I've called it in my head since I tend to use it only when dealing with streams. In this case it would be the insertion operator as you say, rather than just stream operator. I've updated my answer to remove that bit. – Rich Adams Jun 05 '10 at 20:11
17

it's very easy, just implement :

std::ostream & operator<<(std::ostream & os, const myclass & foo)
{
   os << foo.var;
   return os;
}

You need to return a reference to os in order to chain the outpout (cout << foo << 42 << endl)

Tristram Gräbener
  • 9,601
  • 3
  • 34
  • 50
12

Even though other answer provide correct code, it is also recommended to use a hidden friend function to implement the operator<<. Hidden friend functions has a more limited scope, therefore results in a faster compilation. Since there is less overloads cluttering the namespace scope, the compiler has less lookup to do.

struct myclass { 
    int i;

    friend auto operator<<(std::ostream& os, myclass const& m) -> std::ostream& { 
        return os << m.i;
    }
};

int main() { 
    auto const x = myclass{10};
    std::cout << x;

    return 0;
}
Guillaume Racicot
  • 39,621
  • 9
  • 77
  • 141
  • 1
    What do you mean by "hidden"? I can see the function, so it's not hiding very well. – NathanOliver Mar 16 '21 at 20:40
  • @NathanOliver I've borrowed the name from [p1601](http://wg21.link/p1601). Should this be called in a different way? – Guillaume Racicot Mar 16 '21 at 20:43
  • No, it's fine. I just never heard the term before. After reading Walter's paper, it makes more sense. – NathanOliver Mar 16 '21 at 20:48
  • should the definition be together with the declaration in this case? – Michele Piccolini Feb 10 '22 at 13:51
  • @MichelePiccolini I don't get what you mean. If you define the free function outside of the class, it also declares it there, so everyone that can see the definition outside of the class would have to process overload resolution on it, even if the class is unrelated, leading to longer compile time if it's in a header. You could put the definition in a cpp if you want, as long as there is a definition somewhere. I prefer putting them in the class, it's simpler and compiles fast. – Guillaume Racicot Feb 10 '22 at 15:10
  • @GuillaumeRacicot nevermind, I was trying this with the definition and the declaration separate, but I has a typo in the return type in one of them and therefore I was getting errors. I thought that there was some reason why I couldn't have them separate, silly me. Anyways, the first this I would do is to put the definition in the cpp file of the class, and keeping the declaration in the class which lives in the header. Isn't this the structure that speeds up compilation the most? Are you saying that if all the definitions are in the header it's faster? – Michele Piccolini Feb 10 '22 at 15:15
  • @MichelePiccolini Putting the definition in the cpp would be the fastest. Just don't make it visible outside of the class for other translation units. When the declaration of a free function is only found in a class, the compiler can only resolve it through ADL. Keep all operators as hidden friends, and the compiler will have only a handful of candidates to consider instead of tens. If you put the definition (or the declaration) in a header outside of the class, this is where you have slowdown. Keep this in mind when making templates and constexpr functions/classes. – Guillaume Racicot Feb 10 '22 at 15:23
-5

Alternative:

struct myclass { 
    int i;
    inline operator int() const 
    {
        return i; 
    }
};
Emil Mocan
  • 51
  • 7