У меня есть проект, который в настоящее время заблокирован в 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
Это работает довольно хорошо, и std::filesystem::path
теперь доступно. Я тестировал создание и использование path
объекты и это работает.
По мере продвижения вперед я знаю, что мне понадобится больше вещей. Я задавался вопросом, может ли быть способ просто внести все это:
namespace std {
namespace filesystem {
using std::experimental::filesystem::v1;
}
}
Это казалось шагом назад. Ничто не кажется видимым. Оглядываясь назад, я думаю, что это имеет смысл, поскольку сфера действия using
Оператор заканчивается закрывающей скобкой на следующей строке.
Далее я хочу получить directory_entry
, Кажется, работает та же техника
namespace std {
namespace filesystem {
using directory_entry = std::experimental::filesystem::v1::directory_entry;
}
}
Опять же, компилятор выглядит счастливым.
Теперь я хочу использовать std::directory::create_directories
, Однако это функция, а не класс, поэтому тот же метод не сработает.
я думал так std::function
может быть специально для этого, но мне не повезло. Я старался
namespace std {
namespace filesystem {
function<bool(path)> create_directories = std::experimental::filesystem::v1::create_directories;
}
}
и компилятор говорит
Error C2440 'initializing': cannot convert from 'overloaded-function' to 'std::function<bool (std::filesystem::path)>'
Есть две перегрузки функции (одна принимает второй аргумент, чтобы вернуть код ошибки, а не выдавать исключение).
Я застрял. Это должно быть возможно, но мой C ++ — foo слабый.
Ответ лежит в сообщении об ошибке, и помощь, необходимая для создания экземпляра std::function
для перегруженного метода. Благодаря MFisherKDX за то, что указал мне Вот и к W.F. для ответа, что работает.
Игнорируя вопрос о том, является ли законным, моральным или хорошим вкусом расширение стандартного пространства имен (потому что в этом случае я считаю, что это как минимум 2 из 3), вот мой полностью прокомментированный обходной путь:
#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
ОБНОВИТЬ: Себастьян было самое простое решение.
#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
Кстати, для gcc 7.3 требуется почти такой же обходной путь, кроме случаев, когда вы не можете
#include <filesystem>
но должен
#include <experimental/filesystem>
вместо
Других решений пока нет …