C++ 20 source_location 分析

呼延修然
2023-12-01

C++20推出了source_location类,用于记录文件名、行号以及函数名。在C++20之前,一般使用 __FILE____LINE____FUNCION__的预定义宏调用方式。

source_location 声明

source_location 的声明很简单,一个静态成员函数返回当前行的信息,一个构造函数,其余是返回数据成员的函数。

namespace std {
  struct source_location {
    // 静态函数
    static consteval source_location current() noexcept;
    // 构造
    constexpr source_location() noexcept;
 
    // 成员访问
    constexpr uint_least32_t line() const noexcept;
    constexpr uint_least32_t column() const noexcept;
    constexpr const char* file_name() const noexcept;
    constexpr const char* function_name() const noexcept;
 
  private:
    uint_least32_t line_;              // 行号
    uint_least32_t column_;            // 列号 
    const char* file_name_;            // 文件名 
    const char* function_name_;        // 函数名 
  };
}

source_location 用法

用法很简单,一般使用场景用于日志输出,如:

void log(std::string_view message,
         const std::source_location& location = std::source_location::current())
{
    std::cout << "info:"
              << location.file_name() << ':'
              << location.line() << ' '
              << message << '\n';
}
 
int main()
{
    log("Hello world!");
}

自己实现source_location

source_location 是一个很简单的类,其核心是利用了__builtin_FILE()__builtin_FUNCTION()__builtin_LINE()__builtin_COLUMN()。(相关资料:https://gcc.gnu.org/onlinedocs/gcc-4.8.0/gcc/Other-Builtins.html#index-g_t_005f_005fbuiltin_005fFILE-3359)

这里个人进行了一些简化,未考虑编译器的兼容,同时current()std不同,自行实现版本:

struct source_location {
    constexpr source_location(const char* file_name = __builtin_FILE(),
        const char* function_name = __builtin_FUNCTION(),
        unsigned int line = __builtin_LINE()) noexcept
        : file_name_(file_name), function_name_(function_name), line_(line) {}

    static constexpr source_location current() noexcept { return sourc_location(); }
    constexpr const char* file_name() const noexcept { return file_name_; }
    constexpr const char* function_name() const noexcept { return function_name_; }
    constexpr unsigned int line() const noexcept { return line_; }

private:
    const char* file_name_;
    const char* function_name_;
    const unsigned int line_;
};

接下来,看看怎么用:

source_location location;
std::cout << "info: " << location.file_name() << ":" << location.line() << ":"
    << location.column() << ":" << location.function_name() << ": "
    << "01 Hello World!" << std::endl;

附录

其他实现版本:source_location (github.com)

std::source_location - cppreference.com

Other Builtins - Using the GNU Compiler Collection (GCC)

 类似资料: