How to define a static operator<<?

2019-02-10 18:46发布

Is it possible to define a static insertion operator which operates on the static members of a class only? Something like:

class MyClass
{
public:
    static std::string msg;

    static MyClass& operator<< (const std::string& token) {
        msg.append(token);
        return *this;   // error, static
    }
};

alternatively:

static MyClass& operator<< (MyClass&, const std::string &token)
{
    MyClass::msg.append(token);
    return ?;
}

This is how I would like to use it:

MyClass << "message1" << "message2";

Thank you!

4条回答
淡お忘
2楼-- · 2019-02-10 19:09

If all the members of MyClass are static, it's possible to return a fresh instance.

However, returning a reference poses a problem. There are two solutions:

  • define a static instance
  • pass by copy, and not by reference.

The second approach is easiest:

static MyClass operator<< (MyClass, const std::string &token)
{
     MyClass::msg.append(token);
     return MyClass();
}

The first is one line more:

static MyClass& operator<< (MyClass&, const std::string &token)
{
     static MyClass instance;

     MyClass::msg.append(token);
     return instance;
}

Usage is very close to what you want:

MyClass() << "message1" << "message2";

However, I would not recommend to do this. Why don't you just just use a std::ostringstream? You'll get formatting and some more for free. If you really need global access, declare a global variable.

查看更多
迷人小祖宗
3楼-- · 2019-02-10 19:17

You can't. A class-name / type is not a value in itself, you would need an expression like

class Foobar {...};

std::cout << Foobar << std::endl;

so that your static operator<< would be usable, but that is not valid C++. The grammar summary at A.4 shows that putting a type's name there is not valid.

Consider also that operator overloads are just functions with flaky names:

T  operator<< (T, T)
   ^^^^^^^^^^ flaky name, basically same as:
T  left_shift (T, T)

And functions in C++ (and most other languages, e.g. C#) can only work on instances of types, not types themselves.

However, C++ offers templates which have type arguments, howhowever, that would not help you to overload functions upon types.

查看更多
甜甜的少女心
4楼-- · 2019-02-10 19:21

If you want to use your class as cout, what you can do is example

#include <iostream>
using namespace std;
namespace trace
{
  class trace
  {
  public:
    trace& operator<< (const std::string& echo)
    {
      std::cout << echo << std::endl;
      return *this;
    }
  };

  trace t; // Note that we created variable so we could use it.
};

using namespace trace; // Note that we use same namespace so we dont need to do trace::t
int main(int argv, char** argc)
{
  t << "Server started..."
    << "To exit press CTRL + Z";
  return 0;
}

Output should look like each string in new line like this:

Server started... To exit press CTRL + Z

查看更多
forever°为你锁心
5楼-- · 2019-02-10 19:27

What I would probably do in your situation, is create another class that overloads the operator<<, then make a static member of that type. Like this:

class MyClass
{
public:
    static std::string msg;

    struct Out {
        Out & operator<< (const std::string& token) {
            MyClass::msg.append(token);
            return *this;
        }
    };

    static Out out;    
};

Using it is not quite what you asked for, but close enough I think:

MyClass::out << "message1" << "message2";
查看更多
登录 后发表回答