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

How do I use the __cpp_lib_* feature test macros?

我想使用 feature test macros 检查 std::filesystem 是否可用,但即使我知道 std::filesystem 存在,__cpp_lib_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

Here it is on Compiler Explorer.

我也试过包含 <version>,但是对于 GCC 8.1,它不存在:

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

此外,the note here 说:

Library feature-test macros - defined in the header <version> (C++20)

这意味着库功能测试宏不在 <version> 中直到 C++20,这不适用于 C++17(尽管我不是非常清楚这是否意味着 header 是 C++20 功能,或者 macros 是否是 C++20 功能)。

现在,在这种特殊情况下,我知道我可以通过以下方式对其进行测试:

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

这在这里行得通,因为文件系统是在 C++17 中正式添加的,并且 __has_include 自 C++17 以来就已经存在(或者可能更早,我不知道)——也就是说,不应该不会出现 __has_include 不可用但 std::filesystem 可用的情况。所以没关系。

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

有两种使用__cpp_lib_XXX宏的方法:

  1. 其实包含了对应的header:https://godbolt.org/z/xo68acnrz

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