[英]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
__has_include()
defined(_MSC_VER) && !(defined(_HAS_CXX17) && _HAS_CXX17)
<filesystem>
header exists, but std::filesystem
doesn't.<filesystem>
标头可能存在,但std::filesystem
不存在。 This line checks for that case and uses the experimental version instead.#error ...
INCLUDE_STD_FILESYSTEM_EXPERIMENTAL
namespace filesystem = experimental::filesystem;
std::filesystem
, assuming your compiler let's you do it (I haven't seen a single one that doesn't allow that).std::filesystem
,假设你的编译器让你这样做(我没有看到一个不允许这样做的)。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.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_filesystem
和using
关键字。
// 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.