Как определить статический оператор <<? - PullRequest
4 голосов
/ 23 ноября 2011

Можно ли определить статический оператор вставки, который работает только со статическими членами класса?Что-то вроде:

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

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

альтернативно:

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

Вот как я хотел бы использовать это:

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

Спасибо!

Ответы [ 4 ]

10 голосов
/ 23 ноября 2011

Что бы я, вероятно, сделал в вашей ситуации, - это создать другой класс, который перегружает operator<<, а затем сделать статический член этого типа. Как это:

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

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

    static Out out;    
};

Использование не вполне , что вы просили, но достаточно близко, я думаю:

MyClass::out << "message1" << "message2";
4 голосов
/ 23 ноября 2011

Если все члены MyClass являются статическими, можно вернуть новый экземпляр.

Однако возврат ссылки создает проблему.Существует два решения:

  • определение статического экземпляра
  • передача по копии, а не по ссылке.

Второй подход проще всего:

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

Первая на одну строку больше:

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

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

Использование очень близко к тому, что вы хотите:

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

Однако, Iне рекомендовал бы делать это .Почему бы вам просто не использовать std::ostringstream?Вы получите форматирование и еще немного бесплатно.Если вам действительно нужен глобальный доступ, объявите глобальную переменную.

1 голос
/ 11 октября 2012

Если вы хотите использовать свой класс в качестве cout, то вы можете сделать следующее:

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

Вывод должен выглядеть как каждая строка в новой строке, например:

Сервер запущен ... Для выхода нажмите CTRL + Z

0 голосов
/ 23 ноября 2011

Вы не можете.Имя / тип класса не является значением само по себе, вам потребуется выражение типа

class Foobar {...};

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

, чтобы ваш статический operator<< был пригоден для использования, но это не является допустимым C ++.Сводка грамматики на A.4 показывает, что указание имени типа здесь недопустимо.

Учтите также, что перегрузки операторов - это просто функции с ненадежными именами:

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

И функции в C ++ (и большинство других языков, например C #), могут работать только с экземплярами типов, но не с самими типами.

Однако C ++ предлагает шаблоны с аргументами типов, однако, которые не помогут вам перегружать функции типами.

...