简体   繁体   English

如何确定是否使用<filesystem>或者<experimental/filesystem> ?

[英]How to determine whether to use <filesystem> or <experimental/filesystem>?

Is there a way to determine whether I can use the standard <filesystem> (which is available on all modern C++ compilers that support C++17) or <experimental/filesystem> which is used by older compilers.有没有办法确定我是否可以使用标准<filesystem> (在所有支持 C++17 的现代 C++ 编译器上都可用)或<experimental/filesystem>旧编译器使用的。 (For example g++ 6.3, which is the current standard version on Debian Stretch) (例如 g++ 6.3,这是 Debian Stretch 上的当前标准版本)

Knowing which one to use is imporant because the first uses std::filesystem::xxx and the latter std::experimental::filesystem::xxx .知道使用哪个很重要,因为第一个使用std::filesystem::xxx ,后者使用std::experimental::filesystem::xxx

I typically create a header filesystem.hpp with the following content:我通常创建一个包含以下内容的头filesystem.hpp

// We haven't checked which filesystem to include yet
#ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL

// Check for feature test macro for <filesystem>
#   if defined(__cpp_lib_filesystem)
#       define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0

// Check for feature test macro for <experimental/filesystem>
#   elif defined(__cpp_lib_experimental_filesystem)
#       define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1

// We can't check if headers exist...
// Let's assume experimental to be safe
#   elif !defined(__has_include)
#       define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1

// Check if the header "<filesystem>" exists
#   elif __has_include(<filesystem>)

// If we're compiling on Visual Studio and are not compiling with C++17, we need to use experimental
#       ifdef _MSC_VER

// Check and include header that defines "_HAS_CXX17"
#           if __has_include(<yvals_core.h>)
#               include <yvals_core.h>

// Check for enabled C++17 support
#               if defined(_HAS_CXX17) && _HAS_CXX17
// We're using C++17, so let's use the normal version
#                   define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0
#               endif
#           endif

// If the marco isn't defined yet, that means any of the other VS specific checks failed, so we need to use experimental
#           ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
#               define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1
#           endif

// Not on Visual Studio. Let's use the normal version
#       else // #ifdef _MSC_VER
#           define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 0
#       endif

// Check if the header "<filesystem>" exists
#   elif __has_include(<experimental/filesystem>)
#       define INCLUDE_STD_FILESYSTEM_EXPERIMENTAL 1

// Fail if neither header is available with a nice error message
#   else
#       error Could not find system header "<filesystem>" or "<experimental/filesystem>"
#   endif

// We priously determined that we need the exprimental version
#   if INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
// Include it
#       include <experimental/filesystem>

// We need the alias from std::experimental::filesystem to std::filesystem
namespace std {
    namespace filesystem = experimental::filesystem;
}

// We have a decent compiler and can use the normal version
#   else
// Include it
#       include <filesystem>
#   endif

#endif // #ifndef INCLUDE_STD_FILESYSTEM_EXPERIMENTAL

It even creates an alias for std::experimental::filesystem to std::filesystem if the experimental headers are used.如果使用实验头std::experimental::filesystem ,它甚至会为std::experimental::filesystem创建一个别名到std::filesystem
Which means you can simply include this header in place of <filesystem> , use std::filesystem::xxx and enjoy support from older compilers too.这意味着您可以简单地包含这个头文件来代替<filesystem> ,使用std::filesystem::xxx并享受旧编译器的支持。

A few notes on the details of this snippet:关于此代码段的详细信息的一些说明:

  • __cpp_lib_filesystem and __cpp_lib_experimental_filesystem __cpp_lib_filesystem__cpp_lib_experimental_filesystem
    These are Feature Testing Macros .这些是功能测试宏 They should be available when the respecitive headers are available.当相应的标头可用时,它们应该可用。 But VisualStudio 2015 (and below) don't support them.但是 VisualStudio 2015(及以下)不支持它们。 So the rest is just to make sure we can make an accurate assesment, instead of relying on unreliable macros.所以剩下的只是确保我们可以做出准确的评估,而不是依赖不可靠的宏。
  • __has_include()
    While most compilers do have that macro built in, there is no gurantee, as it is not in the standard.虽然大多数编译器都内置了该宏,但没有保证,因为它不在标准中。 My snippet checks for it's existence before it is used.我的代码片段在使用之前会检查它是否存在。 And in case it doesn't exist, we assume we have to use the experimental version to provide maximum compatibility.如果它不存在,我们假设我们必须使用实验版本来提供最大的兼容性。
  • defined(_MSC_VER) && !(defined(_HAS_CXX17) && _HAS_CXX17)
    Some versions of VisualStudio (namely 2015) have just an half arsed implementation of C++17.某些版本的 VisualStudio(即 2015)只有一半的 C++17 实现。 And it's possible that the <filesystem> header exists, but std::filesystem doesn't.并且<filesystem>标头可能存在,但std::filesystem不存在。 This line checks for that case and uses the experimental version instead.这一行检查这种情况并使用实验版本。
  • #error ...
    If the header check is available and we can't find either header we just print a nice error, as there's nothing we can do.如果头检查可用并且我们找不到任何一个头,我们只会打印一个很好的错误,因为我们无能为力。
  • INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
    You even get a marco that let's you know which version is in usage so you could write pre processor statements of your own that deal with the differences between the versions.您甚至会得到一个 marco,让您知道正在使用哪个版本,这样您就可以编写自己的预处理器语句来处理版本之间的差异。
  • namespace filesystem = experimental::filesystem;
    This alias definition is just for convinice that'll make sure that you'll have std::filesystem , assuming your compiler let's you do it (I haven't seen a single one that doesn't allow that).这个别名定义只是为了说服你有std::filesystem ,假设你的编译器让你这样做(我没有看到一个不允许这样做的)。
    According to the standard defining anything in the std namespace is undefined behavior.根据标准,在std命名空间中定义任何东西都是未定义的行为。 So if your compiler, concience, colleguages, code standard or whatever complains, just define namespace fs = std::experimental::filesystem;因此,如果您的编译器、良心、同事、代码标准或任何抱怨,只需定义namespace fs = std::experimental::filesystem; in the upper block and namespace fs = std::filesystem;在上块和namespace fs = std::filesystem; in the lower.在较低。 (Just to be sure, if you do that, remove the namespace std { stuff) (可以肯定的是,如果您这样做,请删除namespace std {东西)

PS: I created the answer and this question, because I spent an awful lot of time getting frustrated with older compilers not having the <filesystem> header. PS:我创建了答案和这个问题,因为我花了很多时间对没有<filesystem>标头的旧编译器感到沮丧。 After a fair amount of research and testing on multiple platforms with multiple compilers and versions of them, I managed to come up with this universal solution.在具有多个编译器和多个版本的多个平台上进行了大量研究和测试后,我设法提出了这个通用解决方案。 I have tested it with VisualStudio, g++ and clang (Only with versions that actually do have at least experimental support for C++17).我已经用 VisualStudio、g++ 和 clang 对其进行了测试(仅适用于实际上至少对 C++17 具有实验性支持的版本)。
Should there be an issue with another compiler, let me know and I'll make it work for it too.如果另一个编译器有问题,请告诉我,我也会让它为它工作。

I typically use the feature test macros a lot for this type of problem.对于此类问题,我通常会大量使用功能测试宏 I am currently faced with this exact problem but I have used __cpp_lib_filesystem along with the using keyword.我目前正面临这个确切的问题,但我使用了__cpp_lib_filesystemusing关键字。

// since C++ 20
#include <version>

#ifdef __cpp_lib_filesystem
    #include <filesystem>
    using fs = std::filesystem;
#elif __cpp_lib_experimental_filesystem
    #include <experimental/filesystem>
    using fs = std::experimental::filesystem;
#else
    #error "no filesystem support ='("
#endif

I am using this on gcc-6 and up as well as clang-6, sadly no older copy of studio to test against but it works on 15.7 and up.我在 gcc-6 及更高版本以及 clang-6 上使用它,遗憾的是没有旧的工作室副本可供测试,但它适用于 15.7 及更高版本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何启用 filesystem.h 或修复实验/文件系统? - How to enable filesystem.h or fix experimental/filesystem? 实验性::文件系统链接器错误 - experimental::filesystem linker error 如何使用cmake确保C ++ 14编译器与实验性文件系统TS库链接? - How do I use cmake to ensure a C++14 compiler links with the experimental filesystem TS library? 我可以在 ndk 和 libc++ 中使用实验文件系统吗 - can I use experimental filesystem in ndk with libc++ 为什么我不能用 <experimental/filesystem> 用g ++ 4.9.2? - Why can't I use <experimental/filesystem> with g++ 4.9.2? 如何在 gcc 8 上使用 std::filesystem? - how to use std::filesystem on gcc 8? std::filesystem 和 std::experimental::filesystem 之间的路径连接差异 - Path concat difference between std::filesystem and std::experimental::filesystem 不同编译器中的std :: filesystem和std :: experimental :: filesystem问题 - std::filesystem and std::experimental::filesystem problem in different compilers 能<filesystem>和分别<experimental filesystem>可用于 Windows 和 Linux?</experimental></filesystem> - Can <filesystem> and respectively <experimental/filesystem> be used for both Windows and Linux? 包含后未声明“std::filesystem”<experimental filesystem></experimental> - 'std::filesystem' has not been declared after including <experimental/filesystem>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM