User defined error types

Let us imagine a some user defined value type (udt) and some user defined error type (err):


  struct udt
  {
    int a{0};
    explicit udt(int _a)
        : a(_a)
    {
    }
    udt() = default;
    int operator*() const { return a; }
  };

  struct err
  {
    int a{0};
    explicit err(int _a)
        : a(_a)
    {
    }
    err() = default;
  };
View this code on Github

Firstly, note that both the udt and err types can be constructed from an int. Thus this won’t compile:


  result<udt, err> res(5);  // fails to compile, cannot convert 'int' to result
View this code on Github

This is because all the implicit constructors self-disable because it could be ambiguous whether you might mean udt or err. This is not a problem, it just requires typing some more so you are explicit as to which you intend:


  // When it is not unambiguous which to construct, we must say which we want same as with std::variant<>
  result<udt, err> res(in_place_type<err>, 5);
  
View this code on Github

Now, what do you think will happen if we try to retrieve a udt from this result holding an err?


  result<udt, err> res(in_place_type<err>, 5);

  // What happens here? What exception type is thrown?
  try
  {
    std::cout << *res.value() << std::endl;
  }
  catch(const std::exception &e)
  {
    std::cerr << "Exception thrown was " << e.what() << std::endl;
  }
  
View this code on Github