Custom Errors in C++
Here’s the translation of the custom errors example to C++:
#include <iostream>
#include <string>
#include <memory>
#include <stdexcept>
// A custom error type usually has the suffix "Error".
class ArgError : public std::runtime_error {
private:
int arg;
std::string message;
public:
ArgError(int a, const std::string& m) : std::runtime_error(m), arg(a), message(m) {}
int getArg() const { return arg; }
const std::string& getMessage() const { return message; }
// Override what() to provide a custom error message
const char* what() const noexcept override {
static std::string error_message;
error_message = std::to_string(arg) + " - " + message;
return error_message.c_str();
}
};
std::pair<int, std::unique_ptr<std::exception>> f(int arg) {
if (arg == 42) {
// Return our custom error.
return {-1, std::make_unique<ArgError>(arg, "can't work with it")};
}
return {arg + 3, nullptr};
}
int main() {
auto [result, err] = f(42);
// dynamic_cast is somewhat similar to errors.As in Go.
// It checks if the exception can be cast to ArgError*,
// returning nullptr if it can't.
if (auto ae = dynamic_cast<ArgError*>(err.get())) {
std::cout << ae->getArg() << std::endl;
std::cout << ae->getMessage() << std::endl;
} else {
std::cout << "err doesn't match ArgError" << std::endl;
}
}
This C++ code demonstrates how to create and use custom error types. Here’s a breakdown of the translation:
We define a custom
ArgError
class that inherits fromstd::runtime_error
. This is similar to implementing theerror
interface in Go.The
ArgError
class includes thearg
andmessage
fields, and provides methods to access them.We override the
what()
method to provide a custom error message, similar to theError()
method in Go.The
f
function returns astd::pair
with the result and astd::unique_ptr<std::exception>
for the error. This is similar to returning multiple values in Go.In the
main
function, we use structured binding to get the result and error fromf
.We use
dynamic_cast
to check if the error is of typeArgError
. This is similar toerrors.As
in Go, but with some differences:dynamic_cast
returnsnullptr
if the cast fails, whileerrors.As
returns a boolean.dynamic_cast
only works with polymorphic types (classes with virtual functions).
If the cast succeeds, we print the
arg
andmessage
from theArgError
.
Note that C++ exception handling is typically used for error handling, but this example demonstrates how to create a custom error type and use it in a way similar to Go’s error handling.
To compile and run this program:
$ g++ -std=c++17 custom_errors.cpp -o custom_errors
$ ./custom_errors
42
can't work with it
This example shows how C++ can implement custom error types and provide similar functionality to Go’s error handling, albeit with some differences due to the language’s design.