Upgrading the Filesystem TS
An Outcome based solution to the dual overload problem is straightforward:
namespace filesystem2
{
// Error code + paths related to a failure. Also causes ADL discovery to check this namespace.
struct failure_info
{
std::error_code ec;
path path1, path2;
};
// Tell Outcome that failure_info is to be treated as a std::error_code
inline const std::error_code &make_error_code(const failure_info &fi) { return fi.ec; }
// Localise an outcome implementation specific to this namespace. Normally would just
// be `result`, but for clarity we'll use `fs_result`.
template <class T> using fs_result = outcome::result<T, failure_info>;
/*! Copies the file at path `from` to path `to`.
\returns Successful if file was successfully copied, otherwise the error code reported
by the operating system plus a payload of the paths involved.
\throws Never throws.
*/
fs_result<void> copy_file(const path &from, const path &to) noexcept;
}
Starting at the bottom, there is now a single copy_file()
function which returns a fs_result<void>
.
As result
is either successful or not, there is no longer any point in returning a boolean, so we
simply return void
on success. On failure, as the template alias fs_result<T>
above it shows,
we are returning a failure_info
structure containing an error code and the same additional information
as filesystem_error
provides.
It is important to note that the fact that failure_info
is defined in namespace filesystem2
is very
important. This is because Outcome uses Argument Dependent Lookup (ADL)
to find the make_error_code()
function, as well as other customisation point free functions. In other words, only the namespaces as
defined by ADL are searched when finding a free function telling us what to do for failure_info
,
which includes the namespace failure_info
is declared into.