26

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 Answers 6

33

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.

3
  • 4
    Mandatory reference to the "Empty Base Optimization" allowed to compilers for those who did not understood the answer :) Commented Jan 28, 2011 at 15:24
  • I am accepting this as the answer, but it should also mention the fact that boost's approach prevents subclassing to explicitly provide the copy functionality. Commented Jan 28, 2011 at 22:15
  • @Mark Borgerding I don't understand what exactly you want to add to my answer. I edited it. If you like to add something else, than tell me.
    – UmmaGumma
    Commented Jan 28, 2011 at 22:59
23

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
4

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.

4

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).

1
  • When did compiler lay-out derived class objects as if the base subobject was a member subobject? It seems to me that reuse of tail padding of base subobject existed for decades (at least one).
    – curiousguy
    Commented Dec 25, 2011 at 23:07
0

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

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?

Not the answer you're looking for? Browse other questions tagged or ask your own question.