[英]Can a define be made across all translation units?
是否可以跨所有翻譯單元進行 #define 或類似的預處理器定義?
標頭實現對於非常小的庫很有用,因為所有代碼都可以包含和分布在具有以下結構的單個標頭中:
// library.h
void libFunc(); // forward decl
#ifdef IMPLEMENT_LIBRARY
int libState;
volatile int libVolState; // library state exposed to external processes
void libFunc(){
// definition
}
#endif
然而,這種結構要求用戶在頭文件只包含在他們的一個翻譯單元中之前定義IMPLEMENT_LIBRARY
,這意味着它不能放在用戶的頭文件中,對於不完全熟悉 C++ 的人來說可能有點混亂編譯規則。
如果有一種方法可以在所有 TU 中定義IMPLEMENT_LIBRARY
,則可以使用以下命令自動完成
#ifndef IMPLEMENT_LIBRARY
#defineToAllUnits IMPLEMENT_LIBRARY
// library state
// definitions
#endif
是否存在這樣的機制,或者當前的單頭系統是否與它會得到的一樣好?
對於這個用例,您可能根本不應該使用宏定義。 如果要在庫用戶的 TU 中定義函數,可以使用內聯函數。 內聯函數可以在多個 TU 中定義(只要定義相同):
// library.h
inline void libFunc(){
// definition
}
另一種方法是單獨編譯庫,並讓庫的用戶與其鏈接,而不是在他們自己的 TU 中定義定義。
關於問題本身
是否可以跨所有翻譯單元進行 #define 或類似的預處理器定義?
可以在多個 TU 中#define 預處理器宏:
// a.cpp
#define foo a
// b.cpp
#define foo b
如果您希望定義在定義它的所有 TU 之間匹配,您可以將宏定義放入頭文件中,並包括:
// h.hpp
#define foo h
// a.cpp
#include "h.hpp"
// b.cpp
#include "h.hpp"
不可能將一個 TU 的定義“注入”到其他 TU 中,因此沒有可能的“#defineToAllUnits”等價物。 它通常是可以從編譯器調用“注入”宏定義: gcc a.cpp b.cpp -Dfoo=h
。 但是,我認為這對您的用例沒有用。
一些編譯單元很可能在包含#defineToAllUnits
編譯單元之前編譯,因此這是不可能的。
在實踐中,您的問題通常是通過使用構建系統將-DIMPLEMENTAT_LIBRARY
選項傳遞給編譯器(或等效語法)來解決的。 另一種可能性,在嘗試通過多個定義實現廣泛的可移植性時很常見,就是在任何地方都包含像config.h
這樣的配置頭config.h
。 該標頭可以在配置時自動生成。
您還可以通過使用inline
函數和變量來避免侵犯 ODR。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.