#include <iostream>
#define TRY(Expr_) \
({ auto result = (Expr_); \
if (!result.ok) { return result; } \
std::move(result.data); })
template <typename E>
struct Error {
Error(E e): error(std::move(e)) {}
E error;
};
template <typename E>
Error<E> error(E e) { return Error<E>(std::move(e)); }
template <typename T, typename E>
struct Result {
template <typename U>
Result(U u): ok(true), data(std::move(u)), error() {}
template <typename F>
Result(Error<F> f): ok(false), data(), error(std::move(f.error)) {}
template <typename U, typename F>
Result(Result<U, F>&& other):
ok(other.ok), data(std::move(other.data)), error(std::move(other.error)) {}
bool ok = false;
T data;
E error;
};
Result<double, std::string> sqrt(double x) {
if (x < 0) {
return error("sqrt does not accept negative numbers");
}
return x;
}
Result<double, std::string> double_sqrt(double x) {
auto y = TRY(sqrt(x));
return sqrt(y);
}
int main() {
double_sqrt(4);
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKI2RlZmluZSBUUlkoRXhwcl8pIFwKICAgICh7IGF1dG8gcmVzdWx0ID0gKEV4cHJfKTsgXAogICAgICAgaWYgKCFyZXN1bHQub2spIHsgcmV0dXJuIHJlc3VsdDsgfSBcCiAgICAgICBzdGQ6Om1vdmUocmVzdWx0LmRhdGEpOyB9KQoKdGVtcGxhdGUgPHR5cGVuYW1lIEU+CnN0cnVjdCBFcnJvciB7CglFcnJvcihFIGUpOiBlcnJvcihzdGQ6Om1vdmUoZSkpIHt9CgkKCUUgZXJyb3I7Cn07Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgRT4KRXJyb3I8RT4gZXJyb3IoRSBlKSB7IHJldHVybiBFcnJvcjxFPihzdGQ6Om1vdmUoZSkpOyB9Cgp0ZW1wbGF0ZSA8dHlwZW5hbWUgVCwgdHlwZW5hbWUgRT4Kc3RydWN0IFJlc3VsdCB7Cgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVT4KCVJlc3VsdChVIHUpOiBvayh0cnVlKSwgZGF0YShzdGQ6Om1vdmUodSkpLCBlcnJvcigpIHt9CgkKCXRlbXBsYXRlIDx0eXBlbmFtZSBGPgoJUmVzdWx0KEVycm9yPEY+IGYpOiBvayhmYWxzZSksIGRhdGEoKSwgZXJyb3Ioc3RkOjptb3ZlKGYuZXJyb3IpKSB7fQoJCgl0ZW1wbGF0ZSA8dHlwZW5hbWUgVSwgdHlwZW5hbWUgRj4KCVJlc3VsdChSZXN1bHQ8VSwgRj4mJiBvdGhlcik6CgkgICAgb2sob3RoZXIub2spLCBkYXRhKHN0ZDo6bW92ZShvdGhlci5kYXRhKSksICBlcnJvcihzdGQ6Om1vdmUob3RoZXIuZXJyb3IpKSB7fQoJCgkKCWJvb2wgb2sgPSBmYWxzZTsKCVQgZGF0YTsKCUUgZXJyb3I7Cn07CgoKUmVzdWx0PGRvdWJsZSwgc3RkOjpzdHJpbmc+IHNxcnQoZG91YmxlIHgpIHsKCWlmICh4IDwgMCkgewoJCXJldHVybiBlcnJvcigic3FydCBkb2VzIG5vdCBhY2NlcHQgbmVnYXRpdmUgbnVtYmVycyIpOwoJfQoJcmV0dXJuIHg7Cn0KClJlc3VsdDxkb3VibGUsIHN0ZDo6c3RyaW5nPiBkb3VibGVfc3FydChkb3VibGUgeCkgewoJYXV0byB5ID0gVFJZKHNxcnQoeCkpOwoJcmV0dXJuIHNxcnQoeSk7Cn0KCmludCBtYWluKCkgewoJZG91YmxlX3NxcnQoNCk7CglyZXR1cm4gMDsKfQ==