C++20 source_location

董庆
2023-12-01

使用source_location类可以减少代码中出现__FILE__ , __FUNCTION__ , __LINE__宏的次数。
https://zh.cppreference.com/w/cpp/utility/source_location

01 source_location头文件

source_location是表示关于源码的信息,例如文件名、行号以及函数名的类。
在头文件<source_location>中。1

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_;         // 仅为阐释
  };
}

02 source_location用法

source_location 类表示关于源码的具体信息,例如文件名、行号以及函数名。以前,希望获得关于调用位置的信息(用于记录、测试或调试目的)的函数必须使用宏,以令如 __LINE____FILE__ 的预定义宏于调用方的环境展开。 source_location 类提供更好的替代。2

source_location类方法说明
current构造对应调用点位置的新 source_location(公开静态成员函数)
line返回此对象所表示的行号
column返回此对象所表示的列号
file_name返回此对象所表示的文件名
function_name返回此对象表示的函数名,若它存在
#include <iostream>
#include <string_view>
#include <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!");
}
// info:main.cpp:15 Hello world!

03 github上一个source_location实现

一个github上面的关于gcc与clang支持的source_location。3
https://github.com/paweldac/source_location

https://github.com/5455945/cpp_demo/blob/master/C%2B%2B20/source_location/source_location.cpp

#include <iostream>
#include <string_view>
// https://github.com/paweldac/source_location
#include "source_location.hpp"

// https://zh.cppreference.com/w/cpp/header/source_location
// https://zh.cppreference.com/w/cpp/utility/source_location
void log(const std::string_view& message, const std::source_location& location = std::source_location::current())
{
    std::cout << "info: "
        << location.file_name() << " "
        << location.function_name() << " "
        << location.line() << " "
        << location.column() << " "
        << message << '\n';
}

int main()
{
    auto location = std::source_location::current();
    std::cout << "info: " << location.file_name() << ":" << location.line() << ":"
        << location.column() << ":" << location.function_name() << ": "
        << "01 Hello World!" << std::endl;

    log("02 Hello world!");

    auto location2 = std::source_location::current(__FILE__, __FUNCTION__, __LINE__, 0);
    std::cout << location2.file_name() << ":" << location2.line() << ":"
        << location2.column() << ":" << location2.function_name() << ": "
        << "03 Hello World!" << std::endl;

    log("04 Hello world!", std::source_location::current(__FILE__, __FUNCTION__, __LINE__, 0));

    return 0;
}

https://github.com/paweldac/source_location/blob/master/include/source_location/source_location.hpp

#ifndef NOSTD_SOURCE_LOCATION_HPP
#define NOSTD_SOURCE_LOCATION_HPP

#pragma once

#include <cstdint>

namespace std {
struct source_location {
public:
#if not defined(__apple_build_version__) and defined(__clang__) and (__clang_major__ >= 9)
    static constexpr source_location current(const char* fileName = __builtin_FILE(),
        const char* functionName = __builtin_FUNCTION(),
        const uint_least32_t lineNumber = __builtin_LINE(),
        const uint_least32_t columnOffset = __builtin_COLUMN()) noexcept
#elif defined(__GNUC__) and (__GNUC__ > 4 or (__GNUC__ == 4 and __GNUC_MINOR__ >= 8))
    static constexpr source_location current(const char* fileName = __builtin_FILE(),
        const char* functionName = __builtin_FUNCTION(),
        const uint_least32_t lineNumber = __builtin_LINE(),
        const uint_least32_t columnOffset = 0) noexcept
#else
    static constexpr source_location current(const char* fileName = "unsupported",
        const char* functionName = "unsupported",
        const uint_least32_t lineNumber = 0,
        const uint_least32_t columnOffset = 0) noexcept
#endif
    {
        return source_location(fileName, functionName, lineNumber, columnOffset);
    }

    source_location(const source_location&) = default;
    source_location(source_location&&) = default;

    constexpr const char* file_name() const noexcept
    {
        return fileName;
    }

    constexpr const char* function_name() const noexcept
    {
        return functionName;
    }

    constexpr uint_least32_t line() const noexcept
    {
        return lineNumber;
    }

    constexpr std::uint_least32_t column() const noexcept
    {
        return columnOffset;
    }

private:
    constexpr source_location(const char* fileName, const char* functionName, const uint_least32_t lineNumber,
        const uint_least32_t columnOffset) noexcept
        : fileName(fileName)
        , functionName(functionName)
        , lineNumber(lineNumber)
        , columnOffset(columnOffset)
    {
    }

    const char* fileName;
    const char* functionName;
    const std::uint_least32_t lineNumber;
    const std::uint_least32_t columnOffset;
};
} // namespace nostd

#endif

  1. <source_location> ↩︎

  2. std::source_location ↩︎

  3. paweldac/source_location ↩︎

 类似资料: