0

Can the following code (I only kept the relevant part) be converted to use a static member function rather than a friend free function? If not, why not? I tried to convert it to use a static member function in multiple different ways and failed (kept getting different compiler errors for different variations), but I gathered from the answer to this question that you could use either one to do the same things. Is this not technically true due to some property of C++ syntax? Where am I going wrong here?

class Tape {
    public:
        friend std::ostream &operator<<(std::ostream &, Tape &);

    private:
        char blank;
        size_t head;
        std::string tape;
}


std::ostream &operator<<(std::ostream &out, Tape &tape) {
    out << tape.tape << std::endl;
    for (size_t i = 0; i < tape.head; i++)
        out << ' ';
    out << '^' << std::endl;
    return out;
}
Community
  • 1
  • 1
James Mazur
  • 3
  • 1
  • 2
  • why do you want it static? – Marco A. Apr 17 '14 at 19:50
  • Without reading further on your question, `friend` declarations can **always** be avoided by introducing a pair of source/sink abstract interfaces. But you need to set them up with some kind of binding/coupling method. In most cases just using `friend` makes this simpler, better readable and might be absolutely OK to be used. – πάντα ῥεῖ Apr 17 '14 at 19:52

2 Answers2

1

According to the C++ Standard

6 An operator function shall either be a non-static member function or be a non-member function and have at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.

So you may not define operator << as a static mamber function of the class. Nevertheless inside the definition of the operator you may use static member functions. For example

#include <iostream>

class A
{
private:
    int x = 10;
public:
    static std::ostream & out( std::ostream &os, const A &a )
    {
        return ( os << a.x );
    }
};

std::ostream & operator <<( std::ostream &os, const A &a )
{
    return ( A::out( os, a ) );
}

int main() 
{
    A a;
    std::cout << a << std::endl;

    return 0;
}

Opposite to C++ in C# operator functions are defined as static.:)

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • Thanks Vlad, in fact I've always known that it would make sense to either use a free function or a member one to overload operators. – Marco A. Apr 17 '14 at 19:55
1

Since the std::ostream argument is the left hand side of the operator, it can't be a member of your class (static or otherwise).

So it has to be a free function, because you can't add members to std::ostream.

It doesn't have to be a friend though, it could instead call a public member.
I personally prefer this method, as it doesn't expose anything to the outside.

class Tape {
    public:
    void print(std::ostream &out) const 
    {
        out << tape << std::endl;
        for (size_t i = 0; i < head; i++)
            out << ' ';
        out << '^' << std::endl;
    }
};


std::ostream& operator<<(std::ostream &out, const Tape &tape) 
{
    tape.print(out);
    return out;
}
molbdnilo
  • 64,751
  • 3
  • 43
  • 82