Saturday, May 12, 2012

ZeroMQ and C++ without exceptions

my comment in reply to martin_sustrik.

I wanted to post some code into the comment but I finally gave up. I will post it here instead. Disclaimer: this code has not been compiled.

class foo
{
public:
  ~foo() {}
  foo(foo&& other) {
    guts.a = std::move(other.a); // no-fail
  }
  foo& operator=(foo other) { // no-fail
    using std::swap; 
    swap(guts.a, other.guts.a); 
    return *this;
  } 
  static optional<foo> init() {
    optional<foo> result; 
    type guts = {}; // ~type() cleans up on exit
    guts.a.reset(new(std::nothrow) int(5));
    if (!guts.a) {return result;} // no foo constructed 
    result.reset(foo(guts)); //no-fail move construction
    return std::move(result); // no-fail move of result
  }
  int do() {return guts.a.get();} // a cannot be empty
private:
  struct type { std::unique_ptr<int> a; };
  type guts;
  foo(); // disabled
  foo(const foo&); // disabled
  foo(type&& gutsArg) {guts.a = std::move(gutsArg.a);} // no-fail
};

auto MyFoo = foo::init();
if (!MyFoo) return;
MyFoo->do();

if you want to return a detailed error from init() change init() to return a tuple:

  static std::tuple<error, optional<foo>> init();
and use tie to break the result into local vars:
  optional<foo> MyFoo;
  error MyError;
  std::tie(MyError, MyFoo) = foo::init();