How to implement a Result type in C++?

2024-09-07

Here is the code to implement a Rust type in C++.

#include <sstream>
#include <string>
#include <system_error>
#include <type_traits>

template <typename T> struct Result {
   Result() = delete;

   template <typename U> Result(const U &v) {
       if constexpr (std::is_same_v<U, std::error_code> ||
                     std::is_same_v<U, std::error_condition>) {
           err = std::error_code(v.value(), v.category());
       } else {
           value = v;
       }
   }

   bool is_err() { return err != std::error_code(); }
   bool is_ok() { return err == std::error_code(); }

   std::string display() {
       auto ss = std::stringstream()
                 << "error code: " << err.value() << ". "
                 << "error mesage: " << err.message() << ".";

       return ss.str();
   }

   T value;
   std::error_code err;

};

#include <iostream>
#include <vector>

Result<std::string> test_result(int index) {
   switch (index) {
   case 0: {
       auto e = make_error_code(std::errc::bad_address);
       return Result<std::string>(e);
   }
   case 1: {
       auto e = make_error_condition(std::errc::bad_file_descriptor);
       return Result<std::string>(e);
   }
   default:
       return Result<std::string>(std::string("hello world"));
   }
}


int main() {
   for (int i = 0; i < 3; i++) {
       auto res = test_result(i);
       if (res.is_err()) {
           std::cout << res.display() << std::endl;
       } else {
           std::cout << res.value << std::endl;
       }
   }
   return 0;
}

Output:

error code: 14. error mesage: Bad address.
error code: 9. error mesage: Bad file descriptor.
hello world