Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

canceling noncopyable feature

9 views
Skip to first unread message

Michal

unread,
Aug 27, 2009, 9:02:26 AM8/27/09
to
Hallo Group Members

The following simple program allows for copying non-copyable function.

#include <boost/noncopyable.hpp>
#include <iostream>

using namespace std;

class Original: boost::noncopyable {

public:
Original() {
cout << "Original constructor" << endl;
}
Original(const Original& rhs) {
// this definition is the reason!!!!
}
};


int main(int argc, char *argv[])
{
Original o;
Original o2 = o;
return 0;
}


Do You know how is it possible?

best regards
Michal

Victor Bazarov

unread,
Aug 27, 2009, 9:11:05 AM8/27/09
to
Michal wrote:
> The following simple program allows for copying non-copyable function.

Why did you say "function"?

> #include <boost/noncopyable.hpp>
> #include <iostream>
>
> using namespace std;
>
> class Original: boost::noncopyable {
>
> public:
> Original() {
> cout << "Original constructor" << endl;
> }
> Original(const Original& rhs) {
> // this definition is the reason!!!!
> }
> };
>
>
> int main(int argc, char *argv[])
> {
> Original o;
> Original o2 = o;
> return 0;
> }
>
>
> Do You know how is it possible?

What does "boost::nocopyable" do? How is it defined? Is it something
like a class with a private copy-constructor and copy assignment op? I
will base my answer on that assumption.

The copy-constructor of your "Original" class makes no attempt to copy
the base class, and the compiler will just use the default constructor
of the base class ('boost::noncopyable') to create the base class subobject.

That is not the same if you don't define the copy constructor yourself.
The compiler-defined copy-constructor uses *copy-construction* for all
base class subobjects and members. If you don't override that
behaviour, it would make it impossible if the base class' copy
constructor is inaccessible.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Fraser Ross

unread,
Aug 27, 2009, 10:35:58 AM8/27/09
to
Thats a big problem. noncopyable doesn't do its job as well as I
thought. I think copy_protected would be a better name. It's a term
that is used. Noncopyable isn't a word.

Fraser.


Fabio Fracassi

unread,
Aug 27, 2009, 11:32:09 AM8/27/09
to

In C++ it is, in this special case unfortunally, possible to change
the access protection of a member during overloading.
In C++03 there is no (portable) way of inhibiting the behaviour of the
derived code.
C++0x will (IIRC) have the [[final]] attribute which would flag
"Original"s declaration/definition of a copy-ctor as an error.

So currently defining a copy-ctor in a class declared as (boost::)
noncopyable is simply a mistake the compiler doesn't catch, so you
have to be careful during code reviews.

boost::noncopyable is more in the nature of documentation anyway, it
just concicely and conveniently declares your default copy-ctor/
operator private, giving it an explicit name which also documents the
reason for doing so. As a nice bonus you get somewhat better error
messages which contain noncopyable a lot, if your classes users do try
to copy it.

HTH

Fabio

Vladimir Jovic

unread,
Aug 27, 2009, 11:37:04 AM8/27/09
to


Increase the warning level of the compiler. For g++ use next options:
-Wall -W

Victor Bazarov

unread,
Aug 27, 2009, 11:55:25 AM8/27/09
to
Fraser Ross wrote:
> Thats a big problem. noncopyable doesn't do its job as well as I
> thought.

It doesn't necessarily means that it's not doing its job *as intended*,
and what you thought isn't necessarily what was intended. What do you
think it would do? Make any descendant class non-copyable? The whole
point is that the object of 'boost::noncopyable', well, can't be copied.
If you create your class based on this, and provide a way around
having to copy the base class, then here you are, your class is
copyable, but the base class is still not copied because it cannot be.

> I think copy_protected would be a better name. It's a term
> that is used. Noncopyable isn't a word.

Why? The class isn't named 'providingalldescendantsfrombeingcopyable',
is it?

mzdude

unread,
Aug 27, 2009, 2:05:55 PM8/27/09
to
On Aug 27, 11:55 am, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> Fraser Ross wrote:
> > Thats a big problem.  noncopyable doesn't do its job as well as I
> > thought.
>
> It doesn't necessarily means that it's not doing its job *as intended*,
> and what you thought isn't necessarily what was intended.  What do you
> think it would do?  Make any descendant class non-copyable?

Yes. Perhaps changing the boost::noncopyable object to hide it's
default
ctor would help.

Then if you have a class derrived from it

class MyClass : boost::noncopyable
{
MyClass() : boost::noncopyable( some_trait ) {}

// then
MyClass( const MyClass &tocpy ) {}

would error because the compiler would subsitute the default
ctor for noncopyable which would be hidden.

I think that would provide a more intuitive interface.

It still wouldn't be perfect. You could intentionally get
around it by

MyClass::MyClass(const MyClass &toCopy )
: boost::noncopyable( some_trait )
{ }

but at least you would have to work at shooting
yourself.

Victor Bazarov

unread,
Aug 27, 2009, 2:18:47 PM8/27/09
to

Yes, and there will be somebody [more radical in their view] who'd come
and complain about that one. Wanna bet?

There is no way to satisfy everybody. Document what the class does and
what the intended use of it is, and let it go. 'boost::noncopyable' is
apparently intended to make a derived class such that the compiler
cannot produce a copy-ctor for it, which, provided the user does not try
to create a copy-ctor him-/herself, will make the derived class
non-copyalble as well.

There are always conditions. Nothing is absolute. Remember "null
references"?

Noah Roberts

unread,
Aug 27, 2009, 2:25:48 PM8/27/09
to
mzdude wrote:
> On Aug 27, 11:55 am, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
>> Fraser Ross wrote:
>>> Thats a big problem. noncopyable doesn't do its job as well as I
>>> thought.
>> It doesn't necessarily means that it's not doing its job *as intended*,
>> and what you thought isn't necessarily what was intended. What do you
>> think it would do? Make any descendant class non-copyable?
>
> Yes. Perhaps changing the boost::noncopyable object to hide it's
> default
> ctor would help.
>
> Then if you have a class derrived from it
>
> class MyClass : boost::noncopyable
> {
> MyClass() : boost::noncopyable( some_trait ) {}
>
> // then
> MyClass( const MyClass &tocpy ) {}
>
> would error because the compiler would subsitute the default
> ctor for noncopyable which would be hidden.

I don't think that noncopyable is meant to keep you from blowing your
brains out. It's meant to be a somewhat language enforced method of
documenting a known aspect of an interface. Anything that derives from
noncopyable is not meant to be copied, that's what the relationship is
documenting. The rest just keeps the compiler from self-generating the
copyable interface...I don't think it was ever meant to try rescuing
people from their own stupidity and I don't see how it even could.

mzdude

unread,
Aug 27, 2009, 4:07:50 PM8/27/09
to

I know macros have a reputation for being *evil* but I think
the following documents the interface and doesn't bring along
any of the derived interface baggage.

#define NON_COPYABLE(x) private: \
##x(##x const & ); \
##x &operator=(##x const ref) const;

class MyClass
{
public:
MyClass();
NON_COPYABLE(MyClass)
};

Victor Bazarov

unread,
Aug 27, 2009, 4:15:28 PM8/27/09
to

I don't like the name. I think it should be different. Something like

#define DECLARE_NON_COPYABLE(x) ...

and if you leave out the closing semicolon, you will actually force the
user to write something similar to a class definition statement:

...
DECLARE_NON_COPYABLE(MyClass);

Of course, the problem is that the macro hides the change in the access
modifiers, everything that follows it will be 'private' unless you
change the modifier (which is sort of ugly). Besides, the class is
still copyable for friends and members...

When C++0x is out, we'll have the luxury of prohibiting copying for good
using the 'delete' syntax, even for members and friends...

Noah Roberts

unread,
Aug 27, 2009, 4:29:20 PM8/27/09
to

I don't think there's much baggage being brought along. The noncopyable
class is meant to be inherited from privately.


>
> #define NON_COPYABLE(x) private: \
> ##x(##x const & ); \
> ##x &operator=(##x const ref) const;
>
> class MyClass
> {
> public:
> MyClass();
> NON_COPYABLE(MyClass)
> };

Except the error generated using the noncopyable class will have
"noncopyable" in it:


1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(6) : error
C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access
private member declared in class 'boost::noncopyable_::noncopyable'
1> d:\boostvs39\include\boost\noncopyable.hpp(27) : see
declaration of 'boost::noncopyable_::noncopyable::noncopyable'
1> d:\boostvs39\include\boost\noncopyable.hpp(22) : see
declaration of 'boost::noncopyable_::noncopyable'
1> This diagnostic occurred in the compiler generated function
'myclass::myclass(const myclass &)'

your version:


1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(15) : error
C2512: 'myclass' : no appropriate default constructor available
1>d:\dev_workspace\experimental\scratch\scratch\main.cpp(16) : error
C2248: 'myclass::myclass' : cannot access private member declared in
class 'myclass'
1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(10) :
see declaration of 'myclass::myclass'
1> d:\dev_workspace\experimental\scratch\scratch\main.cpp(9) :
see declaration of 'myclass'

Also note the extra error regarding the default constructor with yours.
You can't let the default constructor be compiler generated in your
version.

The code:


#define NON_COPYABLE(x) private: \
##x(##x const&); \


##x &operator=(##x const ref) const;

struct myclass
{
NON_COPYABLE(myclass)
};

int main()
{
myclass a;
myclass b = a;
}

And with noncopyable myclass was defined as:

struct myclass : private boost::noncopyable
{
};

So the benefits of using boost::noncopyable over your macro would seem
to me to be:

1) the statement "noncopyable" in the diagnostic error.
2) the ability to use default constructors.

You say there's derived interface baggage but since you inherit
privately I don't think that even affects derived classes that might
also inherit from noncopyable. I don't see any pollution of the
interface since private inheritance is not an is-a type of relationship.

mzdude

unread,
Aug 27, 2009, 5:24:33 PM8/27/09
to
On Aug 27, 4:29 pm, Noah Roberts <roberts.n...@gmail.com> wrote:
> I don't think there's much baggage being brought along.  The noncopyable
> class is meant to be inherited from privately.

It would be interesting to see how many implementations
actually use the private. Refer to the OP.

> So the benefits of using boost::noncopyable over your macro would seem
> to me to be:
>
> 1) the statement "noncopyable" in the diagnostic error.
> 2) the ability to use default constructors.
>
> You say there's derived interface baggage but since you inherit
> privately I don't think that even affects derived classes that might
> also inherit from noncopyable.  I don't see any pollution of the
> interface since private inheritance is not an is-a type of relationship

As with engineering, there are always tradeoffs. The macro
solves the OP's problem. I never claimed it was a perfect
solution.

Noah Roberts

unread,
Aug 27, 2009, 6:47:13 PM8/27/09
to
mzdude wrote:
> On Aug 27, 4:29 pm, Noah Roberts <roberts.n...@gmail.com> wrote:
>> I don't think there's much baggage being brought along. The noncopyable
>> class is meant to be inherited from privately.
>
> It would be interesting to see how many implementations
> actually use the private. Refer to the OP.

The OP is inheriting privately. This is why I use the 'struct' keyword
rather than 'class'. Instinct is that you are inheriting publicly when
you inherit but it's actually private unless specified otherwise with
'class'.

But the question still stands of course and I don't know the answer.

Balog Pal

unread,
Aug 27, 2009, 7:43:38 PM8/27/09
to
"Michal" <rabb...@tenbit.pl>

>
> class Original: boost::noncopyable {
>
> public:
> Original() {
> cout << "Original constructor" << endl;
> }
> Original(const Original& rhs) {
> // this definition is the reason!!!!
> }
> };

The reason indeed.

> int main(int argc, char *argv[])
> {
> Original o;
> Original o2 = o;
> return 0;
> }
> Do You know how is it possible?

How what is possible? You did define a copy ctor for Original, didn't you?
So it is working.
Whay your problem really is?

(note: the base class noncopyable is NOT copied in your copy ctor, it is
just default-inited like in the other ctor....)


Fraser Ross

unread,
Aug 28, 2009, 7:06:13 AM8/28/09
to
Will you be suggesting this change to the Boost administrators?

Fraser.


James Kanze

unread,
Aug 28, 2009, 7:39:15 AM8/28/09
to

> #include <boost/noncopyable.hpp>
> #include <iostream>

> using namespace std;

> class Original: boost::noncopyable {

You lied to the compiler (and to the reader of your code).
First, you said that the object wasn't copiable, then you said
it was. I may be of the old school, but I find lying
despicable.

The simple solution to this problem is to fire the person who
wrote the code.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

James Kanze

unread,
Aug 28, 2009, 7:47:24 AM8/28/09
to
On Aug 27, 8:25 pm, Noah Roberts <roberts.n...@gmail.com> wrote:
> mzdude wrote:
> > On Aug 27, 11:55 am, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> >> Fraser Ross wrote:
> >>> Thats a big problem. noncopyable doesn't do its job as
> >>> well as I thought.
> >> It doesn't necessarily means that it's not doing its job
> >> *as intended*, and what you thought isn't necessarily what
> >> was intended. What do you think it would do? Make any
> >> descendant class non-copyable?

> > Yes. Perhaps changing the boost::noncopyable object to hide
> > it's default ctor would help.

> > Then if you have a class derrived from it

> > class MyClass : boost::noncopyable
> > {
> > MyClass() : boost::noncopyable( some_trait ) {}

> > // then
> > MyClass( const MyClass &tocpy ) {}

> > would error because the compiler would subsitute the default
> > ctor for noncopyable which would be hidden.

> I don't think that noncopyable is meant to keep you from
> blowing your brains out. It's meant to be a somewhat language
> enforced method of documenting a known aspect of an interface.
> Anything that derives from noncopyable is not meant to be
> copied, that's what the relationship is documenting.

I'd agree if you restrict it to directly deriving. When you
derive from boost::noncopyable, you're saying that copying is
*not* allowed. According to the LSP, however, a class which
derives from MyClass, above, is (and should be) allowed to
reactivate copy, since it is a loosening of the
"pre-conditions". (I know, the LSP generally applies to
functions, and not to objects. But I think you get the idea---a
derived class may add functionality, as long as all of the
functionality of the base class still works.)

FWIW, it's not totally inexistant in my derived classes to add a
private copy constructor, to support cloning, even though the
base class forbids copying (by deriving from
Gabi::Util::UncopiableObject---which is probably identical to
boost::noncopyable, but a bit older).

> The rest just keeps the compiler from self-generating the
> copyable interface...I don't think it was ever meant to try
> rescuing people from their own stupidity and I don't see how
> it even could.

The problem with trying to make anything idiot proof is that
nature keeps coming up with better idiots. No matter what you
do, it will fail in the end.

Victor Bazarov

unread,
Aug 28, 2009, 8:04:15 AM8/28/09
to
Fraser Ross wrote:
> Will you be suggesting this change to the Boost administrators?

What change do you mean? Please quote enough of the replied-to article,
otherwise the "train of thought" is off the tracks, so to speak.

Fraser Ross

unread,
Aug 28, 2009, 9:00:44 AM8/28/09
to

"Victor Bazarov"

> Fraser Ross wrote:
>> Will you be suggesting this change to the Boost administrators?
>
> What change do you mean? Please quote enough of the replied-to
> article, otherwise the "train of thought" is off the tracks, so to
> speak.

class noncopyable {
protected:
explicit noncopyable (int) {}
~noncopyable () {}

private:
noncopyable ();
noncopyable (noncopyable const &);
noncopyable & operator=(noncopyable const &);
};


That is the suggestion. It prevents the OP's code compiling at the
expense of having to specifically initialise the base noncopyable.

Fraser.


Juha Nieminen

unread,
Aug 28, 2009, 1:56:35 PM8/28/09
to
James Kanze wrote:
> You lied to the compiler (and to the reader of your code).
> First, you said that the object wasn't copiable, then you said
> it was. I may be of the old school, but I find lying
> despicable.
>
> The simple solution to this problem is to fire the person who
> wrote the code.

I'm not sure it's that simple. It can also be a genuine mistake.

In a long inheritance chain one of the classes buried somewhere in
there might have been made "noncopyable" for some purpose. Then someone
else might inherit from a class inherited from a class inherited... and
so on from that class, and *inadvertedly* write a copy constructor for
it, overriding the one in that "noncopyable" class.

Of course for this to compile this person has to, if I understood
correctly, fail to call the parent class copy constructor in his own. Of
course this is a bad mistake in itself, but it might happen.

The problem is that now, by pure accident, the class has become
copyable even though it should not be, and the compiler is of no help in
catching this.

Victor Bazarov

unread,
Aug 28, 2009, 2:05:30 PM8/28/09
to

Isn't this all at the same level semantically like making class to be
non-derivable ("final")?

peter koch

unread,
Aug 28, 2009, 3:32:36 PM8/28/09
to
On 27 Aug., 15:02, Michal <rabbi...@tenbit.pl> wrote:

boost::non_copyable is simply a class that forbids copying and in
effect prevents direct copying (and copy-construction). Inheriting
from this class will thus prevent the compiler generated copy-
constructor (and assignment operator) from being generated.
But: nothing prevents you from declaring an explicit constructor:
doing so is an obfuscation and indicates that the original programmer
is quite bad.

/Peter

Fraser Ross

unread,
Aug 29, 2009, 5:19:37 AM8/29/09
to
"Victor Bazarov"

> Juha Nieminen wrote:
>>
>> The problem is that now, by pure accident, the class has become
>> copyable even though it should not be, and the compiler is of no help
>> in
>> catching this.
>
> Isn't this all at the same level semantically like making class to be
> non-derivable ("final")?

Its more useful than that. Library code wouldn't want to allow classes
without copying semantics to be copied my mistake.

The final attribute doesn't actually make a class non-derivable. I
think it can be achieved when used with a virtual destructor though.

Fraser.


James Kanze

unread,
Aug 29, 2009, 5:39:29 AM8/29/09
to
On Aug 28, 7:56 pm, Juha Nieminen <nos...@thanks.invalid> wrote:
> James Kanze wrote:
> > You lied to the compiler (and to the reader of your code).
> > First, you said that the object wasn't copiable, then you said
> > it was. I may be of the old school, but I find lying
> > despicable.

> > The simple solution to this problem is to fire the person who
> > wrote the code.

> I'm not sure it's that simple. It can also be a genuine mistake.

Either the class is copiable, or it isn't. If a programmer
can't make up his mind about this, there's a serious problem.

> In a long inheritance chain one of the classes buried
> somewhere in there might have been made "noncopyable" for some
> purpose. Then someone else might inherit from a class
> inherited from a class inherited... and so on from that class,
> and *inadvertedly* write a copy constructor for it, overriding
> the one in that "noncopyable" class.

One can wonder about the wisdom of a long inheritance chain, but
that's not the issue. A derived class is free to offer
additional functionality, including copy, compared to what the
base class offers. I don't see where there's a problem. The
problem is if the author of the base class says both
not-copiable and copiable at the same time.

(Obviously, the derived class can only offer new functionality
if it is capable of implementing it correctly; if the base class
contains data, the derived class probably cannot implement copy
correctly. But in most cases, base classes are interfaces which
don't contain data, so this is often not a problem.)

> Of course for this to compile this person has to, if I
> understood correctly, fail to call the parent class copy
> constructor in his own. Of course this is a bad mistake in
> itself, but it might happen.

It depends. I'd guess that most of the time my derived classes
offer copy, they don't call the base class copy constructor,
since the base class is typically abstract, without data, and
doesn't guarantee copy.

> The problem is that now, by pure accident, the class has
> become copyable even though it should not be,

Should it, or should it not be copiable, that is the question.
The author of the derived class must know this---it's a design
decision. If it should be copiable, he'll have to implement a
copy constructor with the desired semantics. If it shouldn't,
and he implements a copy constructor, there's a serious problem.

> and the compiler is of no help in catching this.

How can it be? The compiler doesn't know the intent or the
design of the class.

Chris M. Thomasson

unread,
Aug 30, 2009, 3:24:50 PM8/30/09
to
"Michal" <rabb...@tenbit.pl> wrote in message
news:m2prahs...@tenbit.pl...

You created an explicit public copy-constructor for `Original'.

0 new messages