我应该如何使std :: filesystem显示符合Visual Studio 2015的标准

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很弱.

jwm*_*jwm 5

答案在于错误消息以及实例化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)

反而