![](/img/trans.png)
[英]Is there a way to detect portably that a standard header is included using macros?
[英]Is there a way to detect if a given header of the C++ Standard Library is included?
更具體地說,是否有可能在編譯時檢測是否包含 C++ 標准 header 文件(比如說<complex>
),並以跨平台和交叉編譯器的方式進行檢測? 我希望它至少可以與 C++11 一起使用,但是為了這個問題,是否有可能適用於任何 C++ 標准?
我知道 C++ 標准庫的實現依賴於編譯器和操作系統,但是 header 是否有一個標准化的保護名稱,一個我可以檢查是否存在的宏?
我遇到了這個: Detect usage of STL in C++ ,這是一個不使用標頭的技巧,還有這個: 有沒有一種方法可以便攜地檢測標准 header 是否包含在宏中? ,它以 C++17 功能回答,實際上更多是關於檢測 function。
我想要的是能夠在代碼中的給定點編寫一些預處理器指令,以判斷是否包含 header(還)。 我以<complex>
(的實現)為例檢查了源代碼,並定義了_GLIBCXX_COMPLEX
,但可能僅針對此實現。
TL;DR :不,除了 C++17 功能#if __has_include(<complex>)
之外,沒有。 無論如何都沒有定義的宏。
長答案:答案分為兩部分。 我從一些標題中讀到的內容,以及我在不同操作系統和不同編譯器上運行的測試。
警告:我也會寫 C,因為一些編譯器使用相同的宏。 我還使用快捷方式“for C”和“for C++”,而不是“when the header complex.h
is included”和“when the header <complex>
is included”。
好的,這是我目前的最佳答案。
complex.h
: 在 C 中,宏_Complex_I
的存在是我認為應該在任何complex.h
header 中定義的唯一宏,因為它由 ISO C99 指定(參見 ISO/IEC 9899:1999/TC3 文本)。 我運行的測試表明這是一個現實的假設。 使用了一些額外的宏,例如用_COMPLEX_H
編譯時似乎定義了_C_COMPLEX_T
,用MSVC編譯時似乎定義了_C_COMPLEX_T。 可能還有其他的,我沒找到,歡迎補充。
但它是 C,而不是 C++,兩者不能混用。
<complex>
: C++ 標准 (ISO/CEI 14882:2011) 沒有指定此類宏。 事實上,它沒有指定包含任何宏(乍一看)。 它確實指定了complex
的 class 的存在,但這並沒有回答問題。 對於我讀到的內容, _COMPLEX_
和_C_COMPLEX_T
似乎在<complex>
header 中為 LLVM-clang 和 MSVC 定義,但也在complex.h
中為 C 數學庫(libm)的蘋果實現定義。
但是,我在 macOS 上使用 LLVM-clang 編譯器進行的測試未能顯示這些宏,而且我找不到讀取該信息的文件。 我還發現 g++ 正在定義_GLIBCXX_COMPLEX
。
如果想要使用早於 C++17 的 C++ 來執行此操作,一種解決方案是使用代碼將運行的給定編譯器和體系結構進行測試。 這很糟糕,但這是我得到的最接近的答案。
我在這里給出了我在不同操作系統上運行的代碼、編譯器選項、它們的版本以及它們提示的結果。 _Complex_I
確實是為所有 C 標頭定義的。
我無法在 macOS 上使用 GCC 和 G++ 運行測試,但我敢打賭_Complex_I
將使用 GCC 和_GLIBCXX_COMPLEX
定義為 G++。
G++ -std=c++11 v9.3.0 on Ubuntu 20.04: _GLIBCXX_COMPLEX
G++ -std=c++11 v11.2.0 on windows 10(通過 Cygwin):_ _GLIBCXX_COMPLEX
MSVC 默認 c++11 選項 v14.29.xxxxx.x on windows 10: _C_COMPLEX_T
_COMPLEX_
Apple LLVM-clang -std=c++11 v10.0.1: None (並不意味着沒有,只是我不知道是哪一個)
#include <iostream>
#include <complex>
int main(){
#ifdef _COMPLEX_
std::cout << "_COMPLEX_" << std::endl;
#endif
#ifdef _C_COMPLEX_T
std::cout << "_C_COMPLEX_T" << std::endl;
#endif
#ifdef _COMPLEX_H
std::cout << "_COMPLEX_H" << std::endl;
#endif
#ifdef _Complex_I
std::cout << "_Complex_I" << std::endl;
#endif
#ifdef _GLIBCXX_COMPLEX
std::cout << "_GLIBCXX_COMPLEX" << std::endl;
#endif
return 0;
}
GCC -std=c99 v9.3.0 on Ubuntu 20.04: _Complex_I
_COMPLEX_H
GCC -std=c99 v11.2.0 on windows 10(通過 Cygwin): _COMPLEX_H
_Complex_I
windows 10 上的 MSVC -std=c99 v14.29.xxxxx.x: _Complex_I
_C_COMPLEX_T
Apple LLVM-clang -std=c99 v10.0.1: _Complex_I
#include <stdlib.h>
#include <stdio.h>
#include <complex.h>
int main(){
#ifdef _COMPLEX_
printf("_COMPLEX_\n");
#endif
#ifdef _C_COMPLEX_T
printf("_C_COMPLEX_T\n");
#endif
#ifdef _COMPLEX_H
printf("_COMPLEX_H\n");
#endif
#ifdef _Complex_I
printf("_Complex_I\n");
#endif
#ifdef _GLIBCXX_COMPLEX
printf("_GLIBCXX_COMPLEX\n");
#endif
return 0;
}
MSVC is defining _C_COMPLEX_T
whatever C or C++ used, and also _COMPLEX_
for C++. _Complex_I
is always defined for C, and G++ seems to define _GLIBCXX_COMPLEX
whatever the plateform (test to be done on macOS) for C++.
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.