Search code examples
c++visual-studio-2017macrospreprocessorline-numbers

How to get the line number from the call site using __LINE__ or some other method?


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.


Solution

  • 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__)
    

    C++ 20 and beyond

    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