如何确定是否使用< filesystem>或< experimental / filesystem&gt ;? [英] How to determine whether to use <filesystem> or <experimental/filesystem>?

查看:83
本文介绍了如何确定是否使用< filesystem>或< experimental / filesystem&gt ;?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有一种方法可以确定我是否可以使用标准的< filesystem> (可在所有支持C ++ 17的现代C ++编译器上使用)还是< experimental / filesystem> ,由较早的编译器使用。 (例如g ++ 6.3,这是Debian Stretch上的当前标准版本)

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. (For example g++ 6.3, which is the current standard version on Debian Stretch)

知道要使用哪个是重要的,因为第一个使用 std: :filesystem :: xxx 和后者 std :: experimental :: filesystem :: xxx

Knowing which one to use is imporant because the first uses std::filesystem::xxx and the latter std::experimental::filesystem::xxx.

推荐答案

我通常创建带有以下内容的标头 filesystem.hpp

I typically create a header filesystem.hpp with the following content:

// 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

如果使用实验性标头,它甚至会为 std :: experimental :: filesystem std :: filesystem 创建别名。

,这意味着您可以简单地在< filesystem> 处包含此标头,使用 std :: filesystem :: xxx 并获得较早版本的编译器的支持。

It even creates an alias for std::experimental::filesystem to std::filesystem if the experimental headers are used.
Which means you can simply include this header in place of <filesystem>, use std::filesystem::xxx and enjoy support from older compilers too.

此代码段详细信息的一些注意事项:

A few notes on the details of this snippet:


  • __ cpp_lib_filesystem __ cpp_lib_experimental_filesystem

    这些是功能测试宏。当相应的标头可用时,它们应该可用。但是VisualStudio 2015(及更低版本)不支持它们。因此,剩下的只是确保我们可以进行准确的评估,而不是依靠不可靠的宏。

  • __ has_include() < br>
    虽然大多数编译器的确内置了该宏,但没有保证,因为它不在标准中。我的代码段会在使用前检查其是否存在。如果不存在,我们假设必须使用实验版本以提供最大的兼容性。

  • defined(_MSC_VER)&& !(defined(_HAS_CXX17)& __ HAS_CXX17)

    某些版本的VisualStudio(即2015年)仅实现了C ++ 17的一半实现。 < filesystem> 标头可能存在,但 std :: filesystem 不存在。此行将检查这种情况并使用实验版本。

  • #error ...

    如果标头检查可用,我们找不到任何标头,只是打印了一个不错的错误,因为我们无能为力。

  • INCLUDE_STD_FILESYSTEM_EXPERIMENTAL

    您甚至会得到一个marco,让我们知道正在使用哪个版本,因此您可以编写自己的预处理器语句来处理版本之间的差异。

  • 命名空间文件系统=实验性::文件系统;

    此别名定义仅是为了使您确信将拥有 std :: filesystem ,假设编译器让您完成操作(我没有看到一个不允许这样做的编译器)。

    std 命名空间中定义任何内容的标准行为是未定义的行为。因此,如果您的编译器,服务人员,同事,代码标准或任何抱怨的地方,只需在上方的块中定义 namespace fs = std :: experimental :: filesystem; 并在命名空间fs = std :: filesystem; 在下面。 (请确定,如果这样做,请删除名称空间std {东西)

  • __cpp_lib_filesystem and __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. 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. And it's possible that the <filesystem> header exists, but std::filesystem doesn't. 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.
  • 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).
    According to the standard defining anything in the std namespace is undefined behavior. So if your compiler, concience, colleguages, code standard or whatever complains, just define namespace fs = std::experimental::filesystem; in the upper block and namespace fs = std::filesystem; in the lower. (Just to be sure, if you do that, remove the namespace std { stuff)

PS:我创建了答案和这个问题,因为我花了很多时间对没有< filesystem> 标头的较早的编译器感到沮丧。在具有多个编译器和版本的多个平台上进行了大量的研究和测试之后,我设法提出了这个通用解决方案。我已经用VisualStudio,g ++和clang(仅在实际上至少具有对C ++ 17的实验性支持的版本中)进行了测试。

如果其他编译器有问题,请告诉我也会使其适用。

P.S.: 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. 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).
Should there be an issue with another compiler, let me know and I'll make it work for it too.

这篇关于如何确定是否使用&lt; filesystem&gt;或&lt; experimental / filesystem&gt ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆