I have some (in my opinion) fairly specific ownership requirements: I have a class that basically interprets an array of doubles is a specific way (a concatenation of some fairly large matrices), and want to communicate with a C library that interprets then in another way (a very long mathematical vector). In some cases, I want to interpret a pointer that is passed to a callback by the C library, that is, without taking ownership. In that case, copying would be very impractical. In other cases, I want to allocate the buffer myself, and pass it to the C library myself. In that case, my code owns buffer.
I created a "building block" that interprets the double array as the matrices (with boost::numeric::ublas::shallow_array_adaptor
, but that is mostly irrelevant), like this:
class Foo {
public:
explicit Foo(double *buffer);
Foo(const Foo &) = delete;
Foo(Foo &&) = delete;
Foo &operator=(const Foo &) = delete;
/* Some accessors. */
protected:
Foo &operator=(Foo &&) = default;
private:
/* Some things that store pointers into the buffer. */
};
Copying and moving is forbidden so that and instance cannot accidentally be created or moved somewhere which outlives the buffer itself. Of course, deliberate creation of such instances is possible by directly passing the pointer somewhere but can be spotted more easily in the source.
The first part of my question: Does it make sense to let "Foo
enhanced with ownership of the buffer" be a subclass of Foo
?
Every operation of Foo
is possible with the owning-Foo
, additionally, owning-Foo
can be freely copied and moved. It smells like the Liskov substitution principle is satisfied. Being able to handle owning-Foo
and Foo
the same way syntactically without writing a bunch of methods in owning-Foo
that delegate to a member variable is very comfortable.
On the other hand, there could be owner-of-Foo
instead, that deals with the ownership and nothing else, and contains an instance of Foo
that may be accessed from outside, providing better separation of concerns.
I implemented owning-Foo
like this:
class OwningFoo : private std::unique_ptr<double[]>, public Foo {
public:
explicit OwningFoo(std::size_t size)
: std::unique_ptr<double[]>(new double[size]),
Foo(std::unique_ptr<double[]>::get()), size_(size) {
}
/* Implementation of copy and move constructors and
* assignment operators redacted. */
OwningFoo(const OwningFoo &);
OwningFoo(OwningFoo &&);
OwningFoo &operator=(const OwningFoo &);
OwningFoo &operator=(OwningFoo &&);
private:
std::size_t size_;
};
My second part of my question: Is this a good case for multiple and private inheritance? Am I shooting myself in the foot somewhere?
Note that if Foo
is not a member, than std::unique_ptr
can neither be a member, because it needs to be initilized before Foo
.