库基础知识的C ++扩展,版本2 (N4564)引入了类型std::experimental::source_location
。
§14.1.2[reflection.src_loc.creation]说:
static constexpr source_location current() noexcept;
返回:当由函数调用(C ++14§5.2.2)调用时, postfix-expression 是一个(可能是括号内的) id-表达式命名
current
,返回带有实现定义值的source_location
。该值应受#line
(C ++14§16.4)影响,其方式与__LINE__
和__FILE__
相同。如果以其他方式调用,则返回的值未指定。备注:当使用 brace-or-equal-initializer 初始化非静态数据成员时,对
current
的任何调用都应对应于初始化成员的构造函数或聚合初始化的位置。[注意:当用作默认参数时(C ++14§8.3.6),
source_location
的值将是{{1}的调用位置在呼叫站点。 - 结束记录]
如果我理解正确,那么该功能就像这样使用。
current
预期产出:
#include <experimental/source_location> // I don't actually have this header
#include <iostream>
#include <string>
#include <utility>
struct my_exception
{
std::string message {};
std::experimental::source_location location {};
my_exception(std::string msg,
std::experimental::source_location loc = std::experimental::source_location::current()) :
message {std::move(msg)},
location {std::move(loc)}
{
}
};
int
do_stuff(const int a, const int b)
{
if (a > b)
throw my_exception {"a > b"}; // line 25 of file main.cxx
return b - a;
}
int
main()
{
try
{
std::cout << do_stuff(2, 1) << "\n";
}
catch (const my_exception& e)
{
std::cerr << e.location.file_name() << ":" << e.location.line() << ": "
<< "error: " << e.message << "\n";
}
}
如果没有main.cxx:25: error: a > b
,我们可能会使用辅助宏std::experimental::source_location
,它在内部使用THROW_WITH_SOURCE_LOCATION
和__FILE__
宏来正确初始化异常对象。
我想知道图书馆如何实施__LINE__
。除非我完全忽略了这一点,否则如果没有特殊的编译器支持,这样做是不可能的。但是需要什么样的魔术编译器功能才能使其工作?它是否可以与std::experimental::source_location
部署的技巧相媲美?是否有可用于查看此功能的实验性实现?我查了the SVN sources for GCC但还没找到任何内容。
答案 0 :(得分:7)
实现这一点需要编译器的支持。例如,with gcc,您可以使用built-ins functions之类的
int __builtin_LINE()
此函数等效于预处理器
__LINE__
宏,并返回内置调用的行号。在函数F
的C ++默认参数中,它获取对F
的调用的行号。const char * __builtin_FUNCTION()
此函数等效于预处理器
__FUNCTION__
宏,并返回内置调用所在的函数名称。const char * __builtin_FILE()
此函数等效于预处理器
__FILE__
宏,并返回内置调用所在的文件名。在函数F
的C ++默认参数中,它获取文件调用F
的名称。