wovo / hwlib

C++ OO micro-controller library for close-to-the-hardware programming
Boost Software License 1.0
57 stars 26 forks source link

Discussion: move semantics for pin objects #28

Closed JulianvDoorn closed 3 years ago

JulianvDoorn commented 4 years ago

Lately I've ran into an issue where pins are not copyable (which makes sense because you shouldn't have two objects owning the same hardware pin). However C++11 introduced rvalue semantics to improve move semantics.

Now some of my classes use hwlib::target::pin_out, which are constructed separately and provided as a reference with type: hwlib::pin_out&. Now this requires the lifetime of the concrete pin type to be longer than the reference. For factory-like patterns heap usage is usually required, to meet the required object lifetimes.

Providing hwlib::target::pin_out(hwlib::target::pin_out&&) constructors allows for the following pattern (C++17):

class ComplexInterface {
  hwlib::target::pin_out p1;
  hwlib::target::pin_out p2;

  ComplexInterface(hwlib::target::pin_out&& p1, hwlib::target::pin_out&& p2) :
    p1(p1),
    p2(p2)
  { }
};

// For the following code no copies are made, which is 
ComplexInterface createComplexInterface(ComplexInterfaceParams) {
  // initialization code
  return { hwlib::target::pin_out(...), hwlib::target::pin_out(...) };
}

If there any cons to this pattern, I would gladly hear them.

wovo commented 3 years ago

That pattern would only work for target::pin_out, not for any other class that inherist/implements hwlib::pin_out, like the decorators (invert, both, etc.).

That could be solved by making your ComplexInterface a template, with the two pin types as template parameters. I tried that a few years ago, but it got messy very quickly. One problem is when the actual pin_out class has state (like when it is buffered).