如何使用 __cpp_lib_* 功能测试宏?

How do I use the __cpp_lib_* feature test macros?

提问人:Jason C 提问时间:4/22/2022 最后编辑:Jason C 更新时间:4/22/2022 访问量:653

问:

我想使用功能测试宏来检查是否可用,但即使我知道存在,也没有定义。例如,以下测试程序:std::filesystem__cpp_lib_filesystemstd::filesystem

#include <iostream>

int main () {

    std::cout << "__cpp_lib_filesystem: "
#ifdef __cpp_lib_filesystem
        << __cpp_lib_filesystem
#else
        << "not defined"
#endif
        << std::endl;

    std::cout << "__has_include(filesystem): "
#ifndef __has_include
        << "don't have __has_include"
#elif __has_include(<filesystem>)
        << "yes"
#else
        << "no"
#endif
        << std::endl;

}

// also, this compiles:
#include <filesystem>
std::filesystem::path test;

使用 gcc 8.1(我的实际目标编译器)和 gcc 11.2 输出,其中:--std=c++17

__cpp_lib_filesystem: not defined
__has_include(filesystem): yes

这里是编译器资源管理器

我还尝试包括 ,但是,在 GCC 8.1 中,它不存在:<version>

<source>:2:10: fatal error: version: No such file or directory
 #include <version>
          ^~~~~~~~~
compilation terminated.

此外,这里的注释说:

库功能测试宏 - 在标头中定义 <version> (C++20)

除非我误解了,否则这意味着库功能测试宏直到 C++20 才出现,这不适用于 C++17(尽管我不太清楚这是否意味着标头是 C++20 功能,或者是 C++20 功能)。<version>

现在,在这种特殊情况下,我知道我可以通过执行以下操作来测试它:

#if defined(__has_include) && __has_include(<filesystem>)
    // ...
#else
    // ...
#endif

这将在这里起作用,因为文件系统是在 C++ 17 中正式添加的,并且从 C++17 开始就已经存在了(或者可能更早,我不知道)——即不应该出现不可用但可用的情况。所以没关系。__has_include__has_includestd::filesystem

但是,我的问题是:为什么在上面的测试中没有定义它?我错过了什么/我该如何使用它?__cpp_lib_filesystem

C++ GCC C++17 标准

评论

2赞 Eljay 4/22/2022
你似乎不见了.如果包含 或 ,则定义 。#include <version>__cpp_lib_filesystem<version><filesystem>
0赞 Jason C 4/22/2022
@Eljay我真的试过了;但是 GCC 8.1 没有 ,而且关于 cppreference 的注释指出,直到 C++20 才将 lib 功能宏添加到其中。我将用该信息更新问题。<version><version>
0赞 Eljay 4/22/2022
iirc,特性标志是在C++11中引入的,部分用于特性测试,因为许多编译器随着时间的推移零碎地推出特性合规性,直到它们声明特性完成(模错误)。
0赞 Jason C 4/22/2022
我发现这个:en.cppreference.com/w/cpp/header/ciso646 -- 充满希望,但也没有定义宏。如果事情变得可怕,我可能会用语言律师蝙蝠信号来升级它,😂.#include <ciso646>

答:

3赞 Ranoiaetep 4/22/2022 #1

有两种方法可以使用宏:__cpp_lib_XXX

  1. 实际上包括相应的标题:https://godbolt.org/z/xo68acnrz

    • 并且给定的库也需要通过给定的 C++ 版本支持此类功能
      • 例如,即使包含,也不会在 C++17 下定义。__cpp_lib_constexpr_vector<vector>
  2. 使用 C++20,并包含标头。<version>

评论

2赞 Jason C 4/22/2022
明白了;所以对于C++ 17,它归结为首先使用,包括文件,然后测试任何相应的作为对特定功能的确认?__has_include__cpp_lib_*
1赞 Ranoiaetep 4/22/2022
@JasonC 没错
1赞 Jason C 4/22/2022
非常好;谢谢你的回答。