【问题标题】:c++ operator<< as parameterc++ operator<<作为参数
【发布时间】:2016-10-27 16:43:37
【问题描述】:

通常对于 C++ 中的类的重载运算符

template <typename T>
void operator<< (const T &t)
{
    ostringstream stream;
    stream << t;
    // more code
}

我想知道是否有可能使 operatorva_list 创建一个方法来格式化字符串并传递其他参数,例如:

void CBcLogger::print(MLL::ELogLevel lvl, const char* text, ...)

正如您在上述方法中看到的,我可以传递要格式化的文本以及lvl 参数。如果我想使用operator&lt;&lt;,我是否能够以某种方式压缩更多参数而不仅仅是运算符?类似的东西

void multiParamFunc(const unsigned int logLevel, "operator<< here")

我知道这不是正确的语法,但我只是想说明一点。

我将不胜感激有关此案的所有帮助。 另外,我问这个关于纯 c++ 的问题,但最后我会将它与 QT 一起使用。也许这个框架提供了更多的功能?

编辑:我正在制作一个记录器框架。我需要一个允许添加日志行的函数,该行用它的日志杠杆(调试、信息、错误等。它是一个枚举)和一个可以用 operator

例如,print 调用如下所示:

print(MLL::ERROR, "Some text to format %u %i %f", 1, -1, 3.14f);

如您所见,我可以将日志级别参数传递给此函数。我想知道如何使用 operator 实现类似的功能

【问题讨论】:

  • 这是一个经典的 XY 问题:您要问如何实现特定的解决方案,但我们不知道解决方案 什么?你想解决什么问题? 为什么您关心multiParamFunc 接收方法指针(或类型工厂,可能是)?请编辑问题以描述您尝试解决的一般问题,并解释为什么您甚至认为传递运算符是一个好主意。此外,C 风格的可变参数函数不是类型安全的,通常不应使用。现在是 C++11 时代,你不需要它们!
  • 我编辑了问题
  • 将 QStrings 传递给您的记录器是否有问题(理论上它无论如何都需要将它们转换为?)如果没有问题,只需使用 asprintf
  • 我可以这样做,但它看起来不太好,我必须执行类似 `print(MLL:ERROR, "the string %s", myQString.tostd().c_str())' 之类的操作.我不介意函数内部的额外转换只是想尽可能少地写入参数。
  • 我仍然不知道你想做什么。忘记operator&lt;&lt;:毕竟,这是一个实现细节。 你想做什么?举一个例子,使用operator&lt;&lt;,但仍然做你想做的事。

标签: c++ qt operator-overloading operator-keyword


【解决方案1】:

不确定这是否正是您想要做的,但为什么不创建一个包含对适当 ostream 的引用的简单类呢?

class Message : public std::ostream{
  enum LogLevel { DEBUG, INFO, WARNING, ERROR };
  std::ostream* os;
public:
  static LogLevel threshold = DEBUG;
  Message(LogLevel level) : os(0){
    if(level > threshold){
      os = level > INFO ? &std::cerr : &std::cout;
    }
  }

  template<class T> std::ostream& operator<< (const T& t){ 
    return os ? (*os)<<t : this;
  }
};

Message(Message::DEBUG)<<"This won't be printed.\n";
Message(Message::INFO) <<"This will go to stdout.\n";
Message(Message::ERROR)<<"This will go to stderr.\n";

我认为这不会像所写的那样工作,但给出了基本的想法。更高级一点,您可以让 Message 类拥有一个 ostringstream,然后您还可以将其克隆到除 cout/cerr 之外的日志文件,类似于 this

【讨论】:

  • 这正是我的意思。我将尝试实现这一点。我只是想知道如果我必须为每条消息创建一个新对象,这会有多快。
  • @ŁukaszPrzeniosło:由于Message 对象不进行分配,它基本上是即时的。到目前为止,最慢的部分将是流的内部位。
  • 好的,但是您的日志级别阈值是一个常数。在我的框架中,用户必须通过调用包含 print 方法的类的成员来设置此级别。由于我总是创建一个新对象,那么阈值可以存储在哪里?我是否必须以某种方式将此消息类包含在另一个中?
  • 你看过QLoggingCategory和相关流的实现吗?
  • @ŁukaszPrzeniosło:阈值是静态的,但不是恒定的。因此,在处理命令行(或更高版本)期间,如果您想要更详细,您只需执行 Message::threshold = Message::DEBUG