ned14 / outcome

Provides very lightweight outcome<T> and result<T> (non-Boost edition)
https://ned14.github.io/outcome
Other
704 stars 62 forks source link

error code enum to std::error_code conversion #203

Closed DaanDeMeyer closed 4 years ago

DaanDeMeyer commented 5 years ago

If I have a basic_result with EC set to an error code enum class (with a make_error_code overload) and I return this basic_result from a method with a return type of basic_result with EC set to std::error_code, shouldn't the error code enum class be implicitly converted to std::error_code? Right now I'm getting errors that result<T, error code enum> cannot be converted to result<T, std::error_code>.

ned14 commented 5 years ago

A repro would be useful, however make sure that error_code does actually implicitly convert from your EC type, else Outcome won't perform the implicit conversion.

DaanDeMeyer commented 5 years ago

repro:

#include "outcome.hpp"

#include <system_error>

enum class error { test, abcde };

class error_category_impl : public std::error_category {
public:
  const char *name() const noexcept override;

  std::string message(int code) const noexcept override;
};

const char *error_category_impl::name() const noexcept { return "bnl-http3"; }

std::string error_category_impl::message(int code) const noexcept {
  switch (static_cast<error>(code)) {
  case error::test:
    return "test";
  case error::abcde:
    return "abcde";
  }

  return "unknown";
}

const std::error_category &error_category() noexcept {
  static error_category_impl instance;
  return instance;
}

std::error_code make_error_code(error error) noexcept {
  return {static_cast<int>(error), error_category()};
}

namespace std {

template <> struct is_error_code_enum<error> : true_type {};

}

template <typename T>
using enum_result = OUTCOME_V2_NAMESPACE::basic_result<
    T, error, OUTCOME_V2_NAMESPACE::policy::default_policy<T, error, void>>;

enum_result<int> test() {
  return 5;
}

OUTCOME_V2_NAMESPACE::result<int> abc()
{
  std::error_code ec = error::test;
  return test();
}

int main(int argc, char *argv[]) {
  return abc().value();
}

error converts to std::error_code but return test(); in abc fails to compile on my machine (latest clang, Linux).

ned14 commented 5 years ago

I have confirmed this behaviour. This is actually intentional, converting between dissimilar basic_result is explicit, and that is uniform throughout Outcome.

You are supposed to use OUTCOME_TRY to return dissimilar basic_result, and that works right. Is this acceptable in your use cases?

(I agree that the documentation is insufficient here, so I'm leaving this open, tagged Documentation)

DaanDeMeyer commented 5 years ago

It's a minor annoyance when a function delegates to another function as you can't just call return other_function() but its nothing major. Is this supposed to work with only outcome-basic.hpp included? I thought the std integrations all lived in outcome.hpp?

ned14 commented 5 years ago

std integrations live in std_*.hpp.

The big advantage of making most conversions explicit is that it substantially reduces the work that the compiler has to do when compiling Outcome based code. It's tricky to balance the tradeoff between build time impacts and usability, though.

ned14 commented 4 years ago

Necessary documentation page can now be found at https://ned14.github.io/outcome/tutorial/essential/result/try_greedy/