2015-12-21 55 views
6

圖書館基礎知識C++擴展版本2N4564)介紹了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但還沒有找到任何東西。

+7

編譯魔術,按照'std :: type_info' –

+0

@RichardHodges'typeid'可以實現爲一個相當直接的函數。對於非多態類型,編譯器已經知道答案可以直接插入字符串文字,對於多態類型,它必須生成簡單的代碼以在運行時跟隨'vptr'。我不明白'source_location'如何實現同樣簡單。但如果你知道,那就是我正在尋找的答案。 – 5gon12eder

+0

但是如何在沒有編譯器支持的情況下獲得類型名稱?還有很多助手在type_traits中需要編譯器魔術。例如'is_class/enum/union'。 –

回答

6

實現這將需要編譯器的支持。例如,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

+0

酷,這正是我一直在尋找的功能。我不知道他們已經在GCC中實施。特別是默認參數的語義是非凡的(並且確切地說'source_location'需要)。這在我看來,libstdC++可以逃脫,沒有任何額外的魔法。 – 5gon12eder

+0

那麼,除了在鏈接的電子郵件中提到的限制... – 5gon12eder

+0

@ 5gon12eder右邊,電子郵件鏈中的[bugzilla鏈接](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66561)提到了使用現有內置插件的一些限制,但我猜測最終的實現將使用非常相似的東西。 – Praetorian

相關問題