圖書館基礎知識C++擴展版本2(N4564)介紹了std::experimental::source_location
這一類型。std :: experimental :: source_location如何實現?
§14.1.2 [reflection.src_loc.creation]表示:
static constexpr source_location current() noexcept;
返回:當由函數調用調用(C++ 14§5.2.2 ),其後綴表達式是一個(可能爲括號內的)id表達式命名爲
current
,返回source_location
帶有實現定義的值。該值應受#line
(C++ 14§ 16.4)的影響,方式與__LINE__
和__FILE__
相同。如果以其他方式調用,則返回的值是未指定的。備註:當支架 - 或等於初始值設定用於初始化一個非靜態數據成員,
current
任何呼叫應該對應於初始化構件的構造或集合初始化的位置。[注:當作爲默認參數(C++ 14§8.3.6 )中使用的,
source_location
的值將在調用位置的調用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
。除非我完全忽略了這一點,否則沒有特殊的編譯器支持是不可能的。但是,需要什麼樣的魔術編譯器功能才能實現這一功能?它會與std::initializer_list
的技巧相提並論嗎?有沒有這個功能的實驗實現可供查看?我檢查了the SVN sources for GCC但還沒有找到任何東西。
編譯魔術,按照'std :: type_info' –
@RichardHodges'typeid'可以實現爲一個相當直接的函數。對於非多態類型,編譯器已經知道答案可以直接插入字符串文字,對於多態類型,它必須生成簡單的代碼以在運行時跟隨'vptr'。我不明白'source_location'如何實現同樣簡單。但如果你知道,那就是我正在尋找的答案。 – 5gon12eder
但是如何在沒有編譯器支持的情況下獲得類型名稱?還有很多助手在type_traits中需要編譯器魔術。例如'is_class/enum/union'。 –