Consider this short program that I wrote:
#include <iostream>
template<bool Debug = false>
constexpr int add(const int& a, const int& b) {
if (Debug)
std::cout << __FUNCTION__ << " called on line " << __LINE__ << '\n';
return (a + b);
}
int main() {
std::cout << add(3, 7) << '\n';
std::cout << add<true>(5, 9) << '\n';
return 0;
}
It works just fine, and it gives the proper output:
10
add called on line 6
14
However, I'd like for the line number that is printed to be the line at the call site of the program which in this program should be line 12.
So how can I use __LINE__
or some other method to give me the line number from where the function was invoked?
The desired output would be:
10
add called on line 12
14
I would like for it to be generated from the function itself if possible.
-EDIT-
As a note to the reader, I'm open to any and all options but I am limited to C++17 for my current build environment and I'm using Visual Studio.
You can call it like this instead:
template<bool Debug = false>
constexpr int add(const int& a, const int& b, int loc = __LINE__) {
if (Debug)
std::cout << __FUNCTION__ << " called on line " << loc << '\n';
return (a + b);
}
int main() {
std::cout << add(3, 7) << '\n';
std::cout << add<true>(5, 9, __LINE__) << '\n';
return 0;
}
Output:
10
add called on line 14
14
Furthermore, You can define a macro to skip the third argument:
#define add_Debug(a, b) add<true>(a,b,__LINE__)
With C++20, we are getting std::source_location
which contains information about line number, function, file name. If your compiler supports it, you can use that. Example (tested with g++ 9.3.0). You will not need macros anymore:
#include <iostream>
#include <experimental/source_location>
using source_location = std::experimental::source_location;
template<bool Debug = false>
constexpr int add(const int& a, const int& b, source_location l = source_location::current()) {
if (Debug)
// this will print 'main' as function name
//std::cout << l.function_name() << " called on line " << l.line() << //'\n';
std::cout << source_location::current().function_name() << " called on line " << l.line() << '\n';
return (a + b);
}
int main()
{
std::cout << add(3, 7) << '\n';
std::cout << add<true>(5, 9) << '\n';
return 0;
}
Output:
10
add<true> called on line 16
14
With source_location
you don't have to use macros anymore. It will correctly print the line
If you could compile your code on Linux using some recent GCC (in July 2020, that means GCC 10), you might compile with g++ -g -O -Wall
then use Ian Taylor's libbacktrace (like we do in RefPerSys) since that library parses DWARF debug information.
You might either port that library to your operating system and debug info format, or find some equivalent.
Today, a cruder possibility could be to wrap some functions with macros. For example, instead of calling foo()
with some void foo(void);
you would have
extern void foo_at(const char*fileno, int lineno);
#define foo() foo_at(__FILE__,__LINE__);
Indeed, C++20 should add feature tests and source_location
but you might need to wait a few months for a compiler supporting it. Consider compiling a recent GCC from its source code. AFAIK MinGW 64 runs on Windows (so ask permission to use it).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With