有没有办法检测是否包含 C++ 标准库的给定 header?
Is there a way to detect if a given header of the C++ Standard Library is included?
更具体地说,是否可以在编译时检测是否包含 C++ 标准 header 文件(比如 <complex>
),并以 cross-plateform 和 cross-compiler ?我希望它至少可以与 C++11 一起使用,但是为了这个问题,任何 C++ 标准都可以吗?
我知道 C++ 标准库的实现依赖于编译器和操作系统,但是 header 是否有一个标准化的保护名称,一个我可以检查是否存在的宏?
我已经 运行 进入了这个:Detect usage of STL in C++ , which is a hack not to use the headers, and this : ,它用 C++17 特性来回答,实际上更多的是关于检测函数。
我想要的是能够在代码中的给定点编写一些预处理器指令,以判断是否包含 header(还)。我查看了<complex>
(的一个实现)的源代码作为例子,定义了_GLIBCXX_COMPLEX
,但可能只针对这个实现。
TL;DR:不,没有,除了 C++17 特性 #if __has_include(<complex>)
。无论如何都没有定义的宏。
长答案:答案分为两部分。我从一些 header 中读到的内容,以及我 运行 使用不同编译器对不同 OS 进行的测试。
警告:我也会写关于 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 文本)。 I 运行 的测试表明这是一个现实的假设。使用了一些额外的宏,例如 _COMPLEX_H
似乎是在使用 GCC 编译时定义的,
和 _C_COMPLEX_T
使用 MSVC 编译时。可能还有其他的,我没找到,欢迎补充。
但它是 C,不是 C++,两者不能混用。
关于 C++ 和 <complex>
:
C++标准(ISO/CEI 14882:2011)没有指定这样的宏。事实上,它没有指定包含任何宏(乍一看)。
但是,它确实指定了 complex
class 的存在,但这并没有回答问题。
根据我的阅读,_COMPLEX_
和 _C_COMPLEX_T
似乎在 <complex>
header 中定义为
LLVM-clang 和 MSVC,也在 complex.h
中用于 apple 实现的 C 数学库 (libm)。
但是,我在 macOS 上使用 LLVM-clang 编译器进行的测试无法显示这些宏,而且我找不到读取该信息的文件。
我还发现 g++ 正在定义 _GLIBCXX_COMPLEX
.
如果有人想用早于 C++17 的 C++ 来做到这一点,一种解决方案是使用给定的编译器和体系结构测试代码 运行。
这很糟糕,但这是我得到的最接近的答案。
测试:
我在这里给出了我 运行 在不同 OS 上的代码,编译器选项,它们的版本,以及它们提示的结果。 _Complex_I
确实为所有 C header 定义。
我无法使用 GCC 和 G++ 运行 在 macOS 上进行测试,但我敢打赌 _Complex_I
将使用 GCC 定义,_GLIBCXX_COMPLEX
使用 G++ 定义。
C++ 测试
G++ -std=c++11 v9.3.0 在 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 在 windows 10 上:
_C_COMPLEX_T
_COMPLEX_
Apple LLVM-clang -std=c++11 v10.0.1 : None (并不意味着有 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 在 Ubuntu 20.04 上:
_Complex_I
_COMPLEX_H
GCC -std=c99 v11.2.0 on windows 10(通过 Cygwin):
_Complex_I
_COMPLEX_H
MSVC -std=c99 v14.29.xxxxx.x 在 windows 10 上:
_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 正在定义 _C_COMPLEX_T
使用的任何 C 或 C++,并且还为 C++ 定义 _COMPLEX_
。 _Complex_I
总是为 C 定义,而 G++ 似乎为 C++ 定义了 _GLIBCXX_COMPLEX
任何平台(测试要在 macOS 上完成)。
更具体地说,是否可以在编译时检测是否包含 C++ 标准 header 文件(比如 <complex>
),并以 cross-plateform 和 cross-compiler ?我希望它至少可以与 C++11 一起使用,但是为了这个问题,任何 C++ 标准都可以吗?
我知道 C++ 标准库的实现依赖于编译器和操作系统,但是 header 是否有一个标准化的保护名称,一个我可以检查是否存在的宏?
我已经 运行 进入了这个:Detect usage of STL in C++ , which is a hack not to use the headers, and this :
我想要的是能够在代码中的给定点编写一些预处理器指令,以判断是否包含 header(还)。我查看了<complex>
(的一个实现)的源代码作为例子,定义了_GLIBCXX_COMPLEX
,但可能只针对这个实现。
TL;DR:不,没有,除了 C++17 特性 #if __has_include(<complex>)
。无论如何都没有定义的宏。
长答案:答案分为两部分。我从一些 header 中读到的内容,以及我 运行 使用不同编译器对不同 OS 进行的测试。
警告:我也会写关于 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 文本)。 I 运行 的测试表明这是一个现实的假设。使用了一些额外的宏,例如 _COMPLEX_H
似乎是在使用 GCC 编译时定义的,
和 _C_COMPLEX_T
使用 MSVC 编译时。可能还有其他的,我没找到,欢迎补充。
但它是 C,不是 C++,两者不能混用。
关于 C++ 和 <complex>
:
C++标准(ISO/CEI 14882:2011)没有指定这样的宏。事实上,它没有指定包含任何宏(乍一看)。
但是,它确实指定了 complex
class 的存在,但这并没有回答问题。
根据我的阅读,_COMPLEX_
和 _C_COMPLEX_T
似乎在 <complex>
header 中定义为
LLVM-clang 和 MSVC,也在 complex.h
中用于 apple 实现的 C 数学库 (libm)。
但是,我在 macOS 上使用 LLVM-clang 编译器进行的测试无法显示这些宏,而且我找不到读取该信息的文件。
我还发现 g++ 正在定义 _GLIBCXX_COMPLEX
.
如果有人想用早于 C++17 的 C++ 来做到这一点,一种解决方案是使用给定的编译器和体系结构测试代码 运行。 这很糟糕,但这是我得到的最接近的答案。
测试:
我在这里给出了我 运行 在不同 OS 上的代码,编译器选项,它们的版本,以及它们提示的结果。 _Complex_I
确实为所有 C header 定义。
我无法使用 GCC 和 G++ 运行 在 macOS 上进行测试,但我敢打赌 _Complex_I
将使用 GCC 定义,_GLIBCXX_COMPLEX
使用 G++ 定义。
C++ 测试
G++ -std=c++11 v9.3.0 在 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 在 windows 10 上:
_C_COMPLEX_T
_COMPLEX_
Apple LLVM-clang -std=c++11 v10.0.1 : None (并不意味着有 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 在 Ubuntu 20.04 上:
_Complex_I
_COMPLEX_H
GCC -std=c99 v11.2.0 on windows 10(通过 Cygwin):
_Complex_I
_COMPLEX_H
MSVC -std=c99 v14.29.xxxxx.x 在 windows 10 上:
_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 正在定义 _C_COMPLEX_T
使用的任何 C 或 C++,并且还为 C++ 定义 _COMPLEX_
。 _Complex_I
总是为 C 定义,而 G++ 似乎为 C++ 定义了 _GLIBCXX_COMPLEX
任何平台(测试要在 macOS 上完成)。