簡體   English   中英

有沒有辦法檢測是否包含 C++ 標准庫的給定 header?

[英]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”。

好的,這是我目前的最佳答案。

關於 C 和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++,兩者不能混用。

關於 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++。

測試 C++

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 (並不意味着沒有,只是我不知道是哪一個)

C++ 代碼:

#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;
}

C 測試:

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

C 代碼:

#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM