2017-05-27 16:14 GMT+02:00 Niall Douglas via Boost <boost@lists.boost.org>:
This holds in principle but I'm not sure that result<T> should convert into the hypothetical result_e<T>. From the discussion so far, I got the impression that we don't want to return empty results from functions; it seems to follow that result_e<T> would not be a return type, but the type of the local variable in the function that is initially empty but eventually acquires either a value or an error before being returned as result<T>.
That certainly is one design choice. I definitely have functions in KernelTest and AFIO which would be returning a result_e<T> as the empty return is part of the function's public contract. I gave an example of such a function a few days ago.
Sorry, but the amount of threads to follow is getting difficult. Could you point again to the example?
http://boost.2283326.n4.nabble.com/review-Review-of- Outcome-starts-Fri-19-May-tp4694317p4694417.html
Ok, let me quote it here again:
```
// If this is empty, workspaces are identical result<stl1z::filesystem::path> workspaces_not_identical = compare_directories<false, false>(current_test_kernel.working_directory, model_workspace);
// Propagate any error if(workspaces_not_identical.has_error()) testret = error_code_extended(make_error_code(kerneltest_errc::filesystem_comparison_internal_failure),
workspaces_not_identical.get_error().message().c_str(),
workspaces_not_identical.get_error().value());
// Set error with extended message of the path which differs else if(workspaces_not_identical.has_value()) testret = error_code_extended(make_error_code(kerneltest_errc::filesystem_comparison_failed),
workspaces_not_identical.get().string().c_str()); ```
So compare_directories() walks two directory structures using the Filesystem TS and compares them for equivalence using fuzzy criteria. Here we use the empty state to indicate "directory trees are identical", an error state to indicate an error occurred, and a valued state to give the path of the first item which differed.
So, what I am seeing here (correct me if I am wrong), is that conceptually (performance considerations excluded) a return type that clearly reflects your intentions would be: ``` result<optional<filesystem::path>> ``` That is: * either a path representing the first difference, or * no path (but no error) meaning that there was no difference, or * information or error that prefvented you from giving the answer But if you used `result<optional<filesystem::path>>` it would be suboptimal: you have one discriminator for `result` and one for `optional`. So you applied a "hack": since, result's discriminator can handle one additional state fo free, allow it to also represent optional objects. This departs from the philosophy you described earlier, that "empty" state is the most abnormal of all states. But all-in-all the code is faster (I think), but what if in some other project you find it convenient to return "either a filesystem::path or file_desriptor": ``` result<variant<filesystem::path, file_descriptor>> ``` And again, this is suboptimal, as the result's discriminator could also handle two states of the variant's discriminator. Are you going to provide yet another "shades" for `result`: ``` result_variant<filesystem::path, file_descriptor> ``` This is also a useful optimization, but should library handle all possible optimizations for particular problems is user's code? I believe users should apply such improvements themselves, not via a generic tool. Regards, &rzej;