首页 > 解决方案 > 我怎样才能通过 std::basic_streambuf* 进入没有#define的函数

问题描述

我有一个简单的日志类,我想用它来记录哪个文件、行和函数创建了日志消息。我通过以下方式传递信息:

Logger::Log(LoggerLevel::ERROR, __FILE__ << ":" << __LINE__ << "::" << __FUNCTION__ << ":::" << logMessage);

这是我的 Logger 头文件。

#pragma once
#include <iostream>
#include <sstream>

enum class LoggerLevel { ERROR = -1, WARN = 0, INFO = 1, DEBUG = 2, TRACE = 3 };

class Logger
{
public:
  static LoggerLevel logLevel;
  static LoggerLevel GetLoggerLevel();
  static void LogMsg(LoggerLevel anLogLevel, const std::ostream &aMsg);
//  static void Log(LoggerLevel anLogLevel, const std::basic_streambuf<char> *aMsg)
//  {
//    LogMsg(anLogLevel, std::stringstream() << aMsg);
//  }
  
private:
};

#define Log(x, y) Logger::LogMsg(x, std::stringstream() << y)

我想知道如何在不使用底部的#define 的情况下做同样的事情,即使用类似于在我的头文件中注释掉的C++ 函数。

当我尝试使用 C++ 函数时,我收到以下错误消息:

MyClass.cpp:65:44: error: invalid operands of types ‘const char [24]’ and ‘const char [2]’ to binary ‘operator<<’
   65 |   Logger::Log(LoggerLevel::ERROR, __FILE__ << ":" << __LINE__ << "::" << __FUNCTION__ << ":::" << logMsg);
      |                                   ~~~~~~~~ ^~ ~~~
      |                                   |           |
      |                                   |           const char [2]
      |                                   const char [24]

标签: c++loggingstringstreamostream

解决方案


对于 C++14 及更高版本,我所追求的也可以通过一个函数来完成,该函数将 std::string 作为参数并用 + 替换 ostream 插入运算符来连接 std::strings。为了安全起见,我建议使用字符串文字进行连接:

    using namespace std::string_literals;
    Logger::Log(LoggerLevel::ERROR, __FILE__ + ":"s + std::to_string(__LINE__) + "::"s + __FUNCTION__ + ":::"s + logMsg);

Cortex0101 还提供了一个潜在的解决方案,我最初认为它在 C++20 中不起作用,但这只是因为我没有深入搜索标题。

#pragma once
#include <experimental/source_location> // std::experimental::fundamentals_v2::source_location
#include <string>                       // std::string

using src = std::experimental::fundamentals_v2::source_location;

enum class LoggerLevel { ERROR = -1, WARN = 0, INFO = 1, DEBUG = 2, TRACE = 3 };

class Logger
{
public:
  static LoggerLevel logLevel;
  static LoggerLevel GetLoggerLevel();
  static void LogMsg(LoggerLevel anLogLevel, const std::string &aMsg);
  static std::string GetCurrent(src cur)
  {
    using namespace std::string_literals;
    return (cur.file_name()+ ":"s + std::to_string(cur.line()) + "::"s + cur.function_name() + ":::"s);
  }
  
private:
};
Logger::LogMsg(LoggerLevel::INFO, Logger::GetCurrent(src::current()) + logMsg));

推荐阅读