![](/img/trans.png)
[英]C++ - style passing caller file and line to function (equivalent of __FILE__ and __LINE__)
[英]Passing the caller __FILE__ __LINE__ to a function without using macro
我已經習慣了:
class Db {
_Commit(char *file, int line) {
Log("Commit called from %s:%d", file, line);
}
};
#define Commit() _Commit(__FILE__, __LINE__)
但最大的問題是我在全球范圍內重新定義了Commit
這個詞,在 40 萬行的應用程序框架中這是一個問題。 而且我不想使用像DbCommit
這樣的特定詞:我不喜歡像db->DbCommit()
這樣的冗余,或者在任何地方手動傳遞值: db->Commit(__FILE__, __LINE__)
是最糟糕的。
那么,有什么建議嗎?
因此,您希望使用文件和行信息進行日志記錄(或其他操作),並且您寧願不使用宏,對嗎?
歸根結底,它根本無法在 C++ 中完成。 無論您選擇什么機制——內聯函數、模板、默認參數或其他東西——如果你不使用宏,你最終只會得到日志函數的文件名和行號,而不是呼叫點。
使用宏。 這是它們真正不可替代的地方。
甚至C++ FAQ 也說宏有時是兩害相權取其輕的。
正如 Nathon 在下面的評論中所說,在您確實使用宏的情況下,最好明確說明它。 給你的宏宏命名,比如COMMIT()
而不是Commit()
。 這將使維護人員和調試人員清楚地知道有一個宏調用正在進行,並且在大多數情況下應該有助於避免沖突。 兩樣好東西。
等到 C++20,你可以使用 source_location
您可以使用默認參數和預處理器技巧的組合將調用者文件傳遞給函數。 它是以下內容:
函數聲明:
static const char *db_caller_file = CALLER_FILE; class Db { _Commit(const char *file = db_caller_file) { Log("Commit called from %s", file); } };
在類頭文件中聲明db_caller_file
變量。 每個翻譯單元都有一個const char *db_caller_file
。 它是靜態的,因此不會在翻譯單元之間產生干擾。 (沒有多重聲明)。
現在CALLER_FILE
東西,它是一個宏,將從 gcc 的命令行參數生成。 實際上,如果使用自動化的 Make 系統,其中有源文件的通用規則,則要容易得多:您可以添加一個規則來定義以文件名作為值的宏。 例如:
CFLAGS= -MMD -MF $(DEPS_DIR)/$<.d -Wall -D'CALLER_FILE="$<"'
-D
在編譯此文件之前定義一個宏。 $<
是 Make 替換規則先決條件的名稱,在本例中是源文件的名稱。 因此,每個翻譯單元都有自己的db_caller_file
變量,其值為一個字符串,包含文件名。
相同的想法不能應用於呼叫者線路,因為同一翻譯單元中的每個呼叫應該具有不同的行號。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.