diff --git a/include/ghc/filesystem.hpp b/include/ghc/filesystem.hpp index abb8dc3..acb4429 100644 --- a/include/ghc/filesystem.hpp +++ b/include/ghc/filesystem.hpp @@ -1,6 +1,6 @@ //--------------------------------------------------------------------------------------- // -// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17 +// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17/C++20 // //--------------------------------------------------------------------------------------- // @@ -76,6 +76,19 @@ #error "Operating system currently not supported!" #endif #define GHC_OS_DETECTED +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +# if _MSVC_LANG == 201703L +# define GHC_FILESYSTEM_RUNNING_CPP17 +# else +# define GHC_FILESYSTEM_RUNNING_CPP20 +# endif +#elif (defined(__cplusplus) && __cplusplus >= 201703L) +# if __cplusplus == 201703L +# define GHC_FILESYSTEM_RUNNING_CPP17 +# else +# define GHC_FILESYSTEM_RUNNING_CPP20 +# endif +#endif #endif #if defined(GHC_FILESYSTEM_IMPLEMENTATION) @@ -188,6 +201,10 @@ //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp): //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Enforce C++17 API where possible when compiling for C++20, handles the following cases: +// * fs::path::u8string() returns std::string instead of std::u8string +// #define GHC_FILESYSTEM_ENFORCE_CPP17_API +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories // configure LWG conformance () #define LWG_2682_BEHAVIOUR @@ -203,7 +220,7 @@ // * else result of element wise comparison of path iteration where first comparison is != 0 or 0 // if all comparisons are 0 (on Windows this implementation does case insensitive root_name() // comparison) -// #define LWG_2936_BEHAVIOUR +#define LWG_2936_BEHAVIOUR //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2) #define LWG_2937_BEHAVIOUR @@ -217,13 +234,9 @@ // instead of replacing them with the unicode replacement character (U+FFFD). // #define GHC_RAISE_UNICODE_ERRORS //- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -// Enforce C++17 API where possible when compiling for C++20, handles the following cases: -// * fs::path::u8string() returns std::string instead of std::u8string -// #define GHC_FILESYSTEM_ENFORCE_CPP17_API -//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - // ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch) -#define GHC_FILESYSTEM_VERSION 10310L +#define GHC_FILESYSTEM_VERSION 10399L #if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)) #define GHC_WITH_EXCEPTIONS @@ -711,15 +724,11 @@ class GHC_FS_API_CLASS directory_entry // 30.10.12.2 modifiers #ifdef GHC_WITH_EXCEPTIONS void assign(const path& p); -#endif - void assign(const path& p, std::error_code& ec); -#ifdef GHC_WITH_EXCEPTIONS void replace_filename(const path& p); -#endif - void replace_filename(const path& p, std::error_code& ec); -#ifdef GHC_WITH_EXCEPTIONS void refresh(); #endif + void assign(const path& p, std::error_code& ec); + void replace_filename(const path& p, std::error_code& ec); void refresh(std::error_code& ec) noexcept; // 30.10.12.3 observers @@ -727,44 +736,32 @@ class GHC_FS_API_CLASS directory_entry operator const filesystem::path&() const noexcept; #ifdef GHC_WITH_EXCEPTIONS bool exists() const; -#endif - bool exists(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_block_file() const; -#endif - bool is_block_file(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_character_file() const; -#endif - bool is_character_file(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_directory() const; -#endif - bool is_directory(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_fifo() const; -#endif - bool is_fifo(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_other() const; -#endif - bool is_other(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_regular_file() const; -#endif - bool is_regular_file(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_socket() const; -#endif - bool is_socket(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS bool is_symlink() const; -#endif - bool is_symlink(std::error_code& ec) const noexcept; -#ifdef GHC_WITH_EXCEPTIONS uintmax_t file_size() const; + file_time_type last_write_time() const; + file_status status() const; + file_status symlink_status() const; #endif + bool exists(std::error_code& ec) const noexcept; + bool is_block_file(std::error_code& ec) const noexcept; + bool is_character_file(std::error_code& ec) const noexcept; + bool is_directory(std::error_code& ec) const noexcept; + bool is_fifo(std::error_code& ec) const noexcept; + bool is_other(std::error_code& ec) const noexcept; + bool is_regular_file(std::error_code& ec) const noexcept; + bool is_socket(std::error_code& ec) const noexcept; + bool is_symlink(std::error_code& ec) const noexcept; uintmax_t file_size(std::error_code& ec) const noexcept; + file_time_type last_write_time(std::error_code& ec) const noexcept; + file_status status(std::error_code& ec) const noexcept; + file_status symlink_status(std::error_code& ec) const noexcept; #ifndef GHC_OS_WEB #ifdef GHC_WITH_EXCEPTIONS @@ -773,20 +770,6 @@ class GHC_FS_API_CLASS directory_entry uintmax_t hard_link_count(std::error_code& ec) const noexcept; #endif -#ifdef GHC_WITH_EXCEPTIONS - file_time_type last_write_time() const; -#endif - file_time_type last_write_time(std::error_code& ec) const noexcept; - -#ifdef GHC_WITH_EXCEPTIONS - file_status status() const; -#endif - file_status status(std::error_code& ec) const noexcept; - -#ifdef GHC_WITH_EXCEPTIONS - file_status symlink_status() const; -#endif - file_status symlink_status(std::error_code& ec) const noexcept; bool operator<(const directory_entry& rhs) const noexcept; bool operator==(const directory_entry& rhs) const noexcept; bool operator!=(const directory_entry& rhs) const noexcept; @@ -951,224 +934,110 @@ GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) // 30.10.15 filesystem operations #ifdef GHC_WITH_EXCEPTIONS GHC_FS_API path absolute(const path& p); -#endif -GHC_FS_API path absolute(const path& p, std::error_code& ec); - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API path canonical(const path& p); -#endif -GHC_FS_API path canonical(const path& p, std::error_code& ec); - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void copy(const path& from, const path& to); -#endif -GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept; -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void copy(const path& from, const path& to, copy_options options); -#endif -GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API bool copy_file(const path& from, const path& to); -#endif -GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept; -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option); -#endif -GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink); -#endif -GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API bool create_directories(const path& p); -#endif -GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API bool create_directory(const path& p); -#endif -GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API bool create_directory(const path& p, const path& attributes); -#endif -GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink); -#endif -GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link); -#endif -GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept; -#endif - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void create_symlink(const path& to, const path& new_symlink); -#endif -GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API path current_path(); -#endif -GHC_FS_API path current_path(std::error_code& ec); -#ifdef GHC_WITH_EXCEPTIONS GHC_FS_API void current_path(const path& p); +GHC_FS_API bool exists(const path& p); +GHC_FS_API bool equivalent(const path& p1, const path& p2); +GHC_FS_API uintmax_t file_size(const path& p); +GHC_FS_API bool is_block_file(const path& p); +GHC_FS_API bool is_character_file(const path& p); +GHC_FS_API bool is_directory(const path& p); +GHC_FS_API bool is_empty(const path& p); +GHC_FS_API bool is_fifo(const path& p); +GHC_FS_API bool is_other(const path& p); +GHC_FS_API bool is_regular_file(const path& p); +GHC_FS_API bool is_socket(const path& p); +GHC_FS_API bool is_symlink(const path& p); +GHC_FS_API file_time_type last_write_time(const path& p); +GHC_FS_API void last_write_time(const path& p, file_time_type new_time); +GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace); +GHC_FS_API path proximate(const path& p, const path& base = current_path()); +GHC_FS_API path read_symlink(const path& p); +GHC_FS_API path relative(const path& p, const path& base = current_path()); +GHC_FS_API bool remove(const path& p); +GHC_FS_API uintmax_t remove_all(const path& p); +GHC_FS_API void rename(const path& from, const path& to); +GHC_FS_API void resize_file(const path& p, uintmax_t size); +GHC_FS_API space_info space(const path& p); +GHC_FS_API file_status status(const path& p); +GHC_FS_API file_status symlink_status(const path& p); +GHC_FS_API path temp_directory_path(); +GHC_FS_API path weakly_canonical(const path& p); #endif +GHC_FS_API path absolute(const path& p, std::error_code& ec); +GHC_FS_API path canonical(const path& p, std::error_code& ec); +GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept; +GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept; +GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept; +GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept; +GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept; +GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API path current_path(std::error_code& ec); GHC_FS_API void current_path(const path& p, std::error_code& ec) noexcept; - GHC_FS_API bool exists(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool exists(const path& p); -#endif GHC_FS_API bool exists(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool equivalent(const path& p1, const path& p2); -#endif GHC_FS_API bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API uintmax_t file_size(const path& p); -#endif GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept; - -#ifndef GHC_OS_WEB -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API uintmax_t hard_link_count(const path& p); -#endif -GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; -#endif - GHC_FS_API bool is_block_file(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_block_file(const path& p); -#endif GHC_FS_API bool is_block_file(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_character_file(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_character_file(const path& p); -#endif GHC_FS_API bool is_character_file(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_directory(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_directory(const path& p); -#endif GHC_FS_API bool is_directory(const path& p, std::error_code& ec) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_empty(const path& p); -#endif GHC_FS_API bool is_empty(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_fifo(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_fifo(const path& p); -#endif GHC_FS_API bool is_fifo(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_other(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_other(const path& p); -#endif GHC_FS_API bool is_other(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_regular_file(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_regular_file(const path& p); -#endif GHC_FS_API bool is_regular_file(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_socket(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_socket(const path& p); -#endif GHC_FS_API bool is_socket(const path& p, std::error_code& ec) noexcept; GHC_FS_API bool is_symlink(file_status s) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool is_symlink(const path& p); -#endif GHC_FS_API bool is_symlink(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API file_time_type last_write_time(const path& p); -#endif GHC_FS_API file_time_type last_write_time(const path& p, std::error_code& ec) noexcept; -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void last_write_time(const path& p, file_time_type new_time); -#endif GHC_FS_API void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace); -#endif GHC_FS_API void permissions(const path& p, perms prms, std::error_code& ec) noexcept; -GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec); - -#ifdef GHC_WITH_EXCEPTIONS +GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept; GHC_FS_API path proximate(const path& p, std::error_code& ec); -GHC_FS_API path proximate(const path& p, const path& base = current_path()); -#endif GHC_FS_API path proximate(const path& p, const path& base, std::error_code& ec); - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API path read_symlink(const path& p); -#endif GHC_FS_API path read_symlink(const path& p, std::error_code& ec); - GHC_FS_API path relative(const path& p, std::error_code& ec); -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API path relative(const path& p, const path& base = current_path()); -#endif GHC_FS_API path relative(const path& p, const path& base, std::error_code& ec); - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API bool remove(const path& p); -#endif GHC_FS_API bool remove(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API uintmax_t remove_all(const path& p); -#endif GHC_FS_API uintmax_t remove_all(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void rename(const path& from, const path& to); -#endif GHC_FS_API void rename(const path& from, const path& to, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API void resize_file(const path& p, uintmax_t size); -#endif GHC_FS_API void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API space_info space(const path& p); -#endif GHC_FS_API space_info space(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API file_status status(const path& p); -#endif GHC_FS_API file_status status(const path& p, std::error_code& ec) noexcept; - GHC_FS_API bool status_known(file_status s) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API file_status symlink_status(const path& p); -#endif GHC_FS_API file_status symlink_status(const path& p, std::error_code& ec) noexcept; - -#ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API path temp_directory_path(); -#endif GHC_FS_API path temp_directory_path(std::error_code& ec) noexcept; +GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept; +#ifndef GHC_OS_WEB #ifdef GHC_WITH_EXCEPTIONS -GHC_FS_API path weakly_canonical(const path& p); +GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link); +GHC_FS_API uintmax_t hard_link_count(const path& p); +#endif +GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept; +GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; #endif -GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept; // Non-C++17 add-on std::fstream wrappers with path template > @@ -1739,41 +1608,6 @@ inline path::path(const Source& source, format fmt) { postprocess_path_with_format(_path, fmt); } -template <> -inline path::path(const std::wstring& source, format fmt) -{ - _path = detail::toUtf8(source); - postprocess_path_with_format(_path, fmt); -} -template <> -inline path::path(const std::u16string& source, format fmt) -{ - _path = detail::toUtf8(source); - postprocess_path_with_format(_path, fmt); -} -template <> -inline path::path(const std::u32string& source, format fmt) -{ - _path = detail::toUtf8(source); - postprocess_path_with_format(_path, fmt); -} - -#ifdef __cpp_lib_string_view -template <> -inline path::path(const std::string_view& source, format fmt) -{ - _path = detail::toUtf8(std::string(source)); - postprocess_path_with_format(_path, fmt); -} -#ifdef GHC_USE_WCHAR_T -template <> -inline path::path(const std::wstring_view& source, format fmt) -{ - _path = detail::toUtf8(std::wstring(source).c_str()); - postprocess_path_with_format(_path, fmt); -} -#endif -#endif template inline path u8path(const Source& source) @@ -3557,14 +3391,7 @@ GHC_INLINE void copy(const path& from, const path& to) { copy(from, to, copy_options::none); } -#endif - -GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept -{ - copy(from, to, copy_options::none, ec); -} -#ifdef GHC_WITH_EXCEPTIONS GHC_INLINE void copy(const path& from, const path& to, copy_options options) { std::error_code ec; @@ -3575,6 +3402,11 @@ GHC_INLINE void copy(const path& from, const path& to, copy_options options) } #endif +GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept +{ + copy(from, to, copy_options::none, ec); +} + GHC_INLINE void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept { std::error_code tec; @@ -3658,14 +3490,7 @@ GHC_INLINE bool copy_file(const path& from, const path& to) { return copy_file(from, to, copy_options::none); } -#endif - -GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept -{ - return copy_file(from, to, copy_options::none, ec); -} -#ifdef GHC_WITH_EXCEPTIONS GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option) { std::error_code ec; @@ -3677,6 +3502,11 @@ GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option) } #endif +GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept +{ + return copy_file(from, to, copy_options::none, ec); +} + GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept { std::error_code tecf, tect; @@ -4442,7 +4272,7 @@ GHC_INLINE void permissions(const path& p, perms prms, std::error_code& ec) noex permissions(p, prms, perm_options::replace, ec); } -GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) +GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept { if (static_cast(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) { ec = detail::make_error_code(detail::portable_error::invalid_argument); @@ -4491,7 +4321,11 @@ GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::e #ifdef GHC_WITH_EXCEPTIONS GHC_INLINE path proximate(const path& p, std::error_code& ec) { - return proximate(p, current_path(), ec); + auto cp = current_path(ec); + if(!ec) { + return proximate(p, cp, ec); + } + return path(); } #endif