I have a project that is currently locked into Visual Studio 2015. However, I want to write code that is as standards-conforming as possible.
I want to use std::filesystem
but it didn't make it into the standard until C++-17. Fortunately, just about everything is available, just in the std::experimental::filesystem::v1
namespace. I'm not a fan of blanket using
directives; I prefer to scope things fully to make it clear where the thing comes from. So I'm not going to just put in a global using
statement. Some magic is required to convince the compiler to do what I want.
This was my first attempt:
#include <filesystem>
#if defined(_MSC_VER) && _MSC_VER <= 1900 // VS 2015
namespace std {
namespace filesystem {
using path = std::experimental::filesystem::v1::path;
}
}
#endif
That works pretty well, and std::filesystem::path
is now accessible. I've tested creating and using path
objects and it works.
As I move forward, I know I'm going to need more stuff. I wondered if there might be a way to just bring in the whole thing:
namespace std {
namespace filesystem {
using std::experimental::filesystem::v1;
}
}
That seemed like a step backwards. Nothing appears to be visible. In hindsight, I guess it makes sense, since the scope of the using
statement ends with the closing brace on the next line.
Next, I want to get a directory_entry
. The same technique seems to work
namespace std {
namespace filesystem {
using directory_entry = std::experimental::filesystem::v1::directory_entry;
}
}
Again, the compiler seems happy.
Now, I want to use std::directory::create_directories
. However, this is a function, not a class, so the same technique won't work.
I thought that std::function
might be tailor made for this, but I'm not having any luck. I tried
namespace std {
namespace filesystem {
function<bool(path)> create_directories = std::experimental::filesystem::v1::create_directories;
}
}
and the compiler says
Error C2440 'initializing': cannot convert from 'overloaded-function' to 'std::function<bool (std::filesystem::path)>'
There are two overloads of the function (one takes a second argument to return an error code rather than throwing an exception).
I'm stuck. This has to be possible but my C++-foo is weak.
std
namespace is undefined behavior. #37541522 – Scalpelfoo
forstd
the behavior would be the same. And in this case, I consider extending it justified, since the symbols I'm adding are in a later version of the standard. – Trapanusing std::filesystem = std::experimental::filesystem::v1
works? – Cinthiacintronnamespace std { namespace filesystem = experimental::filesystem::v1; }
but I like the idea. – Harveyharvie