jwm*_*jwm 5 c++ visual-studio-2015 std-filesystem
我有一个目前锁定在Visual Studio 2015中的项目.但是,我想编写符合标准的代码.
我想使用std::filesystem它,但直到C++ - 17才进入标准.幸运的是,几乎所有东西都可用,就在std::experimental::filesystem::v1命名空间中.我不喜欢一揽子using指令; 我更喜欢将事情做好,以明确事情的来源.所以我不打算在全球范围内using发表声明.需要一些魔法才能说服编译器按我的意愿行事.
这是我的第一次尝试:
#include <filesystem>
#if defined(_MSC_VER) && _MSC_VER <= 1900 // VS 2015
namespace std {
namespace filesystem {
using path = std::experimental::filesystem::v1::path;
}
}
#endif
Run Code Online (Sandbox Code Playgroud)
这很好用,std::filesystem::path现在可以访问.我测试了创建和使用path对象,它的工作原理.
随着我前进,我知道我将需要更多的东西.我想知道是否有办法引入整个事情:
namespace std {
namespace filesystem {
using std::experimental::filesystem::v1;
}
}
Run Code Online (Sandbox Code Playgroud)
这似乎是倒退了一步.似乎没有任何东西可见.事后来看,我认为这是有道理的,因为using语句的范围以下一行的右括号结束.
接下来,我想得到一个directory_entry.同样的技术似乎有效
namespace std {
namespace filesystem {
using directory_entry = std::experimental::filesystem::v1::directory_entry;
}
}
Run Code Online (Sandbox Code Playgroud)
再次,编译器似乎很高兴.
现在,我想用std::directory::create_directories.但是,这是一个函数,而不是一个类,所以相同的技术将无法工作.
我认为这std::function可能是为此量身定做的,但我没有运气.我试过了
namespace std {
namespace filesystem {
function<bool(path)> create_directories = std::experimental::filesystem::v1::create_directories;
}
}
Run Code Online (Sandbox Code Playgroud)
而编译器说
Error C2440 'initializing': cannot convert from 'overloaded-function' to 'std::function<bool (std::filesystem::path)>'
Run Code Online (Sandbox Code Playgroud)
函数有两个重载(一个使用第二个参数来返回错误代码而不是抛出异常).
我被卡住了.这必须是可能的,但我的C++ - foo很弱.
答案在于错误消息以及实例化std::function重载方法所需的帮助。感谢MFisherKDX指出我在这里并感谢WF提供有效的答案。
忽略扩展标准命名空间是否合法、道德或有品位的问题(因为在这种情况下,我认为它至少是 3 个中的 2 个),这是我完整评论的解决方法:
#if defined(_MSC_VER) && _MSC_VER <= 1900
// Visual Studio 2015 work-around ...
// std::filesystem was incorporated into C++-17 (which is obviously after VS
// 2015 was released). However, Microsoft implemented the draft standard in
// the std::exerimental namespace. To avoid nasty ripple effects when the
// compiler is updated, make it look like the standard here
#include <functional>
namespace std {
namespace filesystem {
using directory_entry = std::experimental::filesystem::v1::directory_entry;
using directory_iterator = std::experimental::filesystem::v1::directory_iterator;
function<bool(path const&)> create_directories =
static_cast<bool(*)(path const&)>(
std::experimental::filesystem::v1::create_directories);
}
}
#endif
Run Code Online (Sandbox Code Playgroud)
更新:塞巴斯蒂安有最简单的解决方案。
#if defined(_MSC_VER) && _MSC_VER <= 1900
// Visual Studio 2015 work-around ...
// std::filesystem was incorporated into C++-17 (which is obviously after VS
// 2015 was released). However, Microsoft implemented the draft standard in
// the std::exerimental namespace. To avoid nasty ripple effects when the
// compiler is updated, make it look like the standard here
namespace std {
namespace filesystem = experimental::filesystem::v1;
}
#endif
Run Code Online (Sandbox Code Playgroud)
顺便说一句,gcc 7.3 需要几乎完全相同的解决方法,除非你不能
#include <filesystem>
Run Code Online (Sandbox Code Playgroud)
但必须
#include <experimental/filesystem>
Run Code Online (Sandbox Code Playgroud)
反而