2

I have the following macro

 #define Error(error_msg) ErrorMsg(__FILE__,__LINE__,error_msg)

I was wondering whether this could be replaced with more modern c++ which can be defined once and for all in a header file?

My function ErrorMsg has following interface

void ErrorMsg(const std::string &file, int line, const std::string &report)
ATK
  • 1,296
  • 10
  • 26
  • 9
    [std::source_location](https://en.cppreference.com/w/cpp/utility/source_location) is C++20 unfortunately. – m88 Mar 11 '21 at 22:16
  • Thanks for the tip!! – ATK Mar 11 '21 at 22:17
  • Didn't know about `source_location`. Thanks @m88 . Everything I can think of loses the correct values for `__FILE__` and `__LINE__`. Could be some arcane template voodoo, but I'm not good with outright voodoo. – user4581301 Mar 11 '21 at 22:17
  • I think std::source_location is the way to go I will flag c++20, and check later if we can upgrade. @m88 would `source_location` be able to detect from which line/file/function it is called without having to feed that explicitly? – ATK Mar 11 '21 at 22:18
  • @user4581301 A seperate question discussing the implementation: https://stackoverflow.com/questions/34405913/how-could-stdexperimentalsource-location-be-implemented. It's just a simple class built over a set of compiler built-ins. – Rane Mar 11 '21 at 22:45
  • 1
    Here is a sample: https://godbolt.org/z/oWrMPW – Jerry Jeremiah Mar 11 '21 at 23:11
  • @JerryJeremiah Looks to me like that would make a good answer. Why don't you post it as such? – Adrian Mole Mar 12 '21 at 00:26
  • @AdrianMole I didn't make it an answer because it wasn't my idea - I kind of thought the person who wrote that first comment should have the right to post the answer. However, since it has been three hours now, it's a pretty safe bet that's not going to happen... – Jerry Jeremiah Mar 12 '21 at 01:41

1 Answers1

5

Like @m88 said in the comments, std::source_location is the modern C++ way to get the filename, function name and line number - so modern, in fact, that it is only supported for really new compilers that support C++20.

Here is a program that does both the macro way and the std::source_location way so that you can compare them:

#include <iostream>
#include <source_location>

void ErrorMsg(const std::string &file, int line, const std::string &message)
{
    std::cout << "info: " << file << ":" << line << ": " << message << "\n";
}

#define ErrorMacro(error_msg) ErrorMsg(__FILE__,__LINE__,error_msg)

void ErrorFunction(const std::string &message, const std::source_location& location = std::source_location::current())
{
    std::cout << "info: "
    << location.file_name() << "("
    << location.line() << ":"
    << location.column() << ") `"
    << location.function_name() << "` "
    << message << '\n';
}

int main()
{
    ErrorMacro("Hello World");    ErrorFunction("Hello World");

    return 0;
}

It produces:

info: ./example.cpp:23: Hello World
info: ./example.cpp(23:62) `int main()` Hello World

Try it at https://godbolt.org/z/xdh4Y6

And here's one where the macro version can print the function name as well:

#include <iostream>
#include <source_location>

void ErrorMsg(const std::string &file, const std::string &function, int line, const std::string &message)
{
    std::cout << "info: " << file << "(" << line << ") `" << function << "` " << message << "\n";
}

#ifdef _MSC_VER
#define ErrorMacro(error_msg) ErrorMsg(__FILE__,__FUNCSIG__,__LINE__,error_msg)
#else
#define ErrorMacro(error_msg) ErrorMsg(__FILE__,__PRETTY_FUNCTION__,__LINE__,error_msg)
#endif

void ErrorFunction(const std::string &message, const std::source_location& location = std::source_location::current())
{
    std::cout << "info: "
    << location.file_name() << "("
    << location.line() << ":"
    << location.column() << ") `"
    << location.function_name() << "` "
    << message << '\n';
}

int main()
{
    ErrorMacro("Hello World");    ErrorFunction("Hello World");

    return 0;
}

It produces:

info: ./example.cpp(27) `int main()` Hello World
info: ./example.cpp(27:62) `int main()` Hello World

Try it at https://godbolt.org/z/13jKfz

Jerry Jeremiah
  • 9,045
  • 2
  • 23
  • 32