Bra*_*one 7 c++ filesystems c++17
有没有办法确定我是否可以使用标准<filesystem>(可在所有支持C++ 17的现代C++编译器上<experimental/filesystem>使用)或旧编译器使用的标准.(例如g ++ 6.3,这是Debian Stretch上的当前标准版本)
知道哪一个使用是有意义的,因为第一次使用std::filesystem::xxx和后者std::experimental::filesystem::xxx.
我通常会创建一个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
Run Code Online (Sandbox Code Playgroud)
它甚至创建了一个别名std::experimental::filesystem到std::filesystem如果使用的实验头.
这意味着你可以简单地包含这个标题代替<filesystem>,使用std::filesystem::xxx并享受旧编译器的支持.
关于此代码段细节的一些注意事项:
__cpp_lib_filesystem而__cpp_lib_experimental_filesystem__has_include()defined(_MSC_VER) && !(defined(_HAS_CXX17) && _HAS_CXX17)<filesystem>标题可能存在,但std::filesystem不存在.此行检查该案例并使用实验版本.#error ...INCLUDE_STD_FILESYSTEM_EXPERIMENTALnamespace filesystem = experimental::filesystem;std::filesystem,并假设你的编译器允许你这样做(我没有看到一个不允许的那个).std命名空间中的任何内容是未定义的行为.因此,如果您的编译器,concience,colleguages,代码标准或任何抱怨,只需namespace fs = std::experimental::filesystem;在上部块和namespace fs = std::filesystem;下部定义.(只是为了确定,如果你这样做,删除namespace std {东西)PS:我创建了答案和这个问题,因为我花了很多时间对没有<filesystem>标题的旧编译器感到沮丧.在使用多个编译器及其版本的多个平台上进行了大量研究和测试之后,我设法提出了这种通用解决方案.我用VisualStudio,g ++和clang测试过它(只有那些实际上至少对C++有实验支持的版本17).
如果有另一个编译器的问题,请告诉我,我也会让它工作.
对于此类问题,我通常会大量使用功能测试宏。我目前正面临这个确切的问题,但我已__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
Run Code Online (Sandbox Code Playgroud)
我在 gcc-6 及更高版本以及 clang-6 上使用它,遗憾的是没有旧的工作室副本进行测试,但它适用于 15.7 及更高版本。
| 归档时间: |
|
| 查看次数: |
3136 次 |
| 最近记录: |