-1

I have a simple log class that I want to use for logging which file, line, and function created the log message. I am passing the information in the following way:

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

Here is my header file for the 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)

I want to know how I can do the same thing without using the #define at the bottom, i.e. using a C++ function similar to the one that is commented out in my header file.

When I try to use the C++ function, I get the following error message:

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]
Xilnik
  • 1
  • 1
  • See https://en.cppreference.com/w/cpp/utility/source_location – Cortex0101 Jun 20 '21 at 15:41
  • 2
    You can't with a syntax like this. If you could change the syntax to `Logger::Log(LoggerLevel::ERROR) << __FILE__ << ":" << __LINE__;` , this could be made to work. – Igor Tandetnik Jun 20 '21 at 15:41
  • @IgorTandetnik I had seen that as an option in my search, but I was hoping there might be another way that others may not have thought of in previous questions. Your response has a similar answer here: https://stackoverflow.com/questions/6168107/how-to-implement-a-good-debug-logging-feature-in-a-project – Xilnik Jun 20 '21 at 15:48

1 Answers1

0

For C++14 and up, what I was after can also be done with a function that takes in a std::string as an argument and replacing the ostream insertion operators with + instead to concatenate std::strings. To be safe, I recommend using string literals for the concatenation:

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

Cortex0101 also provided a potential solution that I initially thought would not work in C++20, but only because I had not searched in depth for the header.

#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));
Xilnik
  • 1
  • 1