why does boost::noncopyable require inheritance

4.9k Views Asked by At

Adding any noncopyable member to a class would prevent the automatic generation of copy construction and assignment operator. Why does boost require inheritance to use noncopyable?

I think I am not alone in my stylistic preference for

class MyUtility : public MyBase
{
   noncopyable guard;
   ...
};

as opposed to

class MyUtility : public MyBase , private noncopyable
{
   ...
};

Dave Abrahams is a smart guy, so he probably considered this possibility. What am I missing? What does inheritence accomplish?

6

There are 6 best solutions below

3
On BEST ANSWER

Because sizeof(boost::noncopyable)!=0. So in this case your class size will be bigger.

Here you can read about the empty base optimization. (look at section "4.7: The Empty Member Optimization").

Edit: The fact, that noncopyable doesn't have public constructors makes it useless for any other use, while classes with public constructor could also be used for other wrong purposes. This is a another reason, why boost chose this approach.

0
On

If you omit the private designation, it becomes almost like English:

// English: this is my car, it is not copyable
class MyCar: noncopyable {};

// my truck is noncopyable, did i mention it's also a vehicle?
class MyTruck: noncopyable, public MyVehicle {};

// My airplane is a vehicle, BTW it's not copyable
class MyAirplane: public MyVehicle, noncopyable {};
0
On

If you could use noncopyable as a member, it would require a public default constructor and destructor. Then people could create instances of noncopyable or even use it as a polymorphic base class without the destructor being virtual. The implementation without any public members simply ensures that it is used solely as a policy class.

0
On

Personally, I prefer the boost syntax. Inheritance is a way to add some properties or features to the whole class, and noncopyable is such a feature. Noncopyable member seems tricky (you actually don't want to add any member, it's a trick). Inheritance is used precisely for what it is designed for.

1
On

The most obvious reason is that the derived class "isA" noncopiable, so using inheritance makes the most sense. The fact that using it in this way doesn't increase the size of the class is also a consideration today (but I think noncopiable preceded the empty base class optimization).

0
On

I have run into this design decision myself and am thinking that the extra self documentation of having it as a member could actually be worth it. For example, someone might question "why is the class non-copyable?".

class VertexBuffer
{
   std::sr1::noncopyable<GLint> m_vbo;
   ...
};

This now specifically tells me that the class is non-copyable because if the OpenGL VBO gets freed twice, it would be an error.

For example, in the example previous; I can copy a dog so why is your car so special that I cannot copy it?

I couple this with things like zeroinitialized / valueinitialized again for the additional documentation that I don't need to ensure these variable have been assigned before I use them.

class VertexBuffer
{
   std::sr1::noncopyable<GLint> m_vbo;
   std::sr1::zeroinitialized<int> m_vertexCount;
};

I am a bit late to this party but does anyone have any more suggestions?