468,170 Members | 2,081 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,170 developers. It's quick & easy.

Avoid automatic copy constructor generation

Hi,

is there a way to avoid the automatic copy constructor generation. I do
not want the object to be non-copyable. I simply do not want that
copying is done by the default copy constructor. But there is a
constructor that accepts the base class. This one should be used for
copying.

In fact i have a set of classes with a common abstract base. The
implementations do not have own data members. They only implement
different functionality. But is makes sense to do assignments and copy
construction between these set of types. This effectively changes the
functionality depending on the current type.
class ContainerBase
{ // ...
};

class Container1
: public ContainerBase
{ // no own data members!
public:
Container1()
{}
Container1(const ContainerBase& r)
: ContainerBase(r)
{}
Container1& operator=(const ContainerBase& r)
{ ContainerBase::operator=(r); return *this; }
};

class Container2
: public ContainerBase
{ // no own data members!
public:
Container2()
{}
Container2(const ContainerBase& r)
: ContainerBase(r)
{}
Container2& operator=(const ContainerBase& r)
{ ContainerBase::operator=(r); return *this; }
};
int main()
{ Container1 c1;
Container2 c2 = c1; // OK
Container1 c3 = c1; // Wrong! Invokes Container1(const Contarine1& r)
return 0;
}
Of course, I could implement the copy constructors to do the same thing
as the constructor from const ContainerBase&. But this is really
unneeded redundancy. And the copy constructor is much more complicated
in the real application than in this small example. Furthermore the auto
generated copy constructor is unusable. It has undefined behavior
because of some special internal storage dependencies. It also has to do
with multiple inheritance, so I could not move the code to a member
function either.

Is there a way to avoid the required redefinition of the copy
constructor for each class?
Marcel
Oct 25 '08 #1
34 3246
Marcel Müller wrote:
is there a way to avoid the automatic copy constructor generation.
Yes: Implement your own copy constructor. That will make the compiler
to not to create a default one.
Oct 25 '08 #2
Marcel Müller wrote:
Hi,

is there a way to avoid the automatic copy constructor generation. I do
not want the object to be non-copyable. I simply do not want that
copying is done by the default copy constructor. But there is a
constructor that accepts the base class. This one should be used for
copying.

In fact i have a set of classes with a common abstract base. The
implementations do not have own data members. They only implement
different functionality. But is makes sense to do assignments and copy
construction between these set of types. This effectively changes the
functionality depending on the current type.
[snip]

What about implementing a copy-constructor for the Base and then have

class Derived_1 : public Base {

Derived_1 ( Base const & other )
: Base ( other )
{}

Derived_1 ( Derived_1 const & other )
: Base ( other )
{}

};

and similarly for Derived_2, ... ?

I think, if the copy-constructor for Base is implemented properly, the
compiler-generated copy-constructor for the derived classes would do the
same thing as the above, so you could even ditch that. Now, _that_ looks
very much like the code, I snipped. I clearly do not understand your
problem. Maybe, you need to post more details, because I lack the
imagination for:
Furthermore the auto
generated copy constructor is unusable. It has undefined behavior
because of some special internal storage dependencies. It also has to do
with multiple inheritance, so I could not move the code to a member
function either.
If that is true, I do not see how the constructors _from_ the base can
possibly work correctly if they are just:
Container1(const ContainerBase& r)
: ContainerBase(r)
{}


Best

Kai-Uwe Bux
Oct 25 '08 #3
Juha Nieminen wrote:
Marcel Müller wrote:
>is there a way to avoid the automatic copy constructor generation.

Yes: Implement your own copy constructor. That will make the compiler
to not to create a default one.
You don't have to implement it. Just declare one. If your program does
not use it, you don't have to define it. And to make sure the program
does not use it, declare it 'private'.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 26 '08 #4
On 2008-10-25 21:55:54 -0400, Victor Bazarov <v.********@comAcast.netsaid:
Juha Nieminen wrote:
>Marcel Müller wrote:
>>is there a way to avoid the automatic copy constructor generation.

Yes: Implement your own copy constructor. That will make the compiler
to not to create a default one.

You don't have to implement it. Just declare one. If your program
does not use it, you don't have to define it. And to make sure the
program does not use it, declare it 'private'.
And a note for the future: with C++0X you don't need to declare it private.

class C
{
public:
C(const C&) = delete;
};

The "= delete" says that it doesn't exist. There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise. These also apply to default constructors, generated
assignment operators, etc.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 26 '08 #5
Hi,

Pete Becker schrieb:
And a note for the future: with C++0X you don't need to declare it private.

class C
{
public:
C(const C&) = delete;
};
thanks! This is the solution.

Unfortunately all my compilers are far away from C++0X, so I have to do
it the hard way so far.
Marcel
Oct 26 '08 #6
"Pete Becker" wrote:
>You don't have to implement it. Just declare one. If your program does
not use it, you don't have to define it. And to make sure the program
does not use it, declare it 'private'.

And a note for the future: with C++0X you don't need to declare it
private.

class C
{
public:
C(const C&) = delete;
};

The "= delete" says that it doesn't exist. There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise. These also apply to default constructors, generated assignment
operators, etc.
I might like that. That's the first exposure I have had to this new
language of which you speak. I think if it is going to take off, it needs a
better name. I thought, and still do, that C++ is a bad name. The God
awful moniker of this thing is even worse than C++ is.

It kind of reminds me of the Microsoft's annoying obsession to use
meaningless words such as "Explorer". I think the idea was that "Explorer"
is a better "Navigator". Maybe people would think that "Gamma" was a better
"C"?
Oct 26 '08 #7
On 2008-10-26 10:53:05 -0400, "osmium" <r1********@comcast.netsaid:
>
I might like that. That's the first exposure I have had to this new
language of which you speak. I think if it is going to take off, it needs a
better name. I thought, and still do, that C++ is a bad name. The God
awful moniker of this thing is even worse than C++ is.
The name C++0x is used to refer to the upcoming standard. Once it
becomes a standard, the language it defines will be called C++.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 26 '08 #8
Pete Becker wrote:
On 2008-10-25 21:55:54 -0400, Victor Bazarov <v.********@comAcast.net>
said:
>Juha Nieminen wrote:
>>Marcel Müller wrote:
is there a way to avoid the automatic copy constructor generation.

Yes: Implement your own copy constructor. That will make the compiler
to not to create a default one.

You don't have to implement it. Just declare one. If your program
does not use it, you don't have to define it. And to make sure the
program does not use it, declare it 'private'.

And a note for the future: with C++0X you don't need to declare it private.

class C
{
public:
C(const C&) = delete;
};

The "= delete" says that it doesn't exist. There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise. These also apply to default constructors, generated
assignment operators, etc.
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?

--
Ian Collins
Oct 26 '08 #9
On 2008-10-26 17:37:53 -0400, Ian Collins <ia******@hotmail.comsaid:
Pete Becker wrote:
>On 2008-10-25 21:55:54 -0400, Victor Bazarov <v.********@comAcast.net>
said:
>>Juha Nieminen wrote:
Marcel Müller wrote:
is there a way to avoid the automatic copy constructor generation.

Yes: Implement your own copy constructor. That will make the compiler
to not to create a default one.

You don't have to implement it. Just declare one. If your program
does not use it, you don't have to define it. And to make sure the
program does not use it, declare it 'private'.

And a note for the future: with C++0X you don't need to declare it private.

class C
{
public:
C(const C&) = delete;
};

The "= delete" says that it doesn't exist. There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise. These also apply to default constructors, generated
assignment operators, etc.
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
A bit of clarity. A private constructor can be implemented, and used by
members and friends. "= delete" says it doesn't exist.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 27 '08 #10
Pete Becker wrote:
There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise.
Will it be possible to call the compiler-generated copy constructor
from a user-defined copy constructor?
Oct 27 '08 #11
Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.

(Moreover, if you are creating a precompiled library you will not get
any error at all. Only when this library is linked against an executable
the linker error will show up. This is ugly.)

With the "= delete" syntax you will get a clear compiler error at
compile time even if you accidentally call the copy constructor from
inside the class itself.
Oct 27 '08 #12
Juha Nieminen wrote:
Ian Collins wrote:
>I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?

Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.
Oct 27 '08 #13
Juha Nieminen wrote:
Ian Collins wrote:
>I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?

Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
Which is why a non-copyable base class is often used.

--
Ian Collins
Oct 27 '08 #14
Juha Nieminen wrote:
Pete Becker wrote:
>There's also "= default", to
tell the compiler to generate the default version even if it wouldn't
otherwise.

Will it be possible to call the compiler-generated copy constructor
from a user-defined copy constructor?
Aren't those exclusive?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Oct 27 '08 #15
On 2008-10-27 15:06:53 -0400, Victor Bazarov <v.********@comAcast.netsaid:
Juha Nieminen wrote:
>Pete Becker wrote:
>>There's also "= default", to tell the compiler to generate the default
version even if it wouldn't
otherwise.

Will it be possible to call the compiler-generated copy constructor
from a user-defined copy constructor?

Aren't those exclusive?
Yes.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 27 '08 #16
Victor Bazarov wrote:
Juha Nieminen wrote:
>Pete Becker wrote:
>>There's also "= default", to tell the compiler to generate the
default version even if it wouldn't
otherwise.

Will it be possible to call the compiler-generated copy constructor
from a user-defined copy constructor?

Aren't those exclusive?
I know that in the next C++ standard it will be possible to call one
constructor from another. Thus I was wondering if it would be possible
to call the compiler-generated copy constructor from a user-defined one.

It would be really nice if this would be possible, as it would make it
much easier to write copy constructors.

One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget. If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatically copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)
Oct 27 '08 #17
Juha Nieminen wrote:
Victor Bazarov wrote:
>Juha Nieminen wrote:
>>Pete Becker wrote:
There's also "= default", to tell the compiler to generate the
default version even if it wouldn't
otherwise.
Will it be possible to call the compiler-generated copy constructor
from a user-defined copy constructor?
Aren't those exclusive?

I know that in the next C++ standard it will be possible to call one
constructor from another. Thus I was wondering if it would be possible
to call the compiler-generated copy constructor from a user-defined one.
If there's a user-defined copy constructor, then there won't be a
compiler-generated one to call.
One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget.
You have a reasonable point, but IMO such a class is already responsible
for too many things. If a member requires special handling during
copying, then it can be wrapped in a class whose copy constructor does
the right thing. That special handling should be the wrapper's only
job. The owner object's default member-wise copy construction will then
do the right thing automatically. (I realize this doesn't reflect most
existing C++ code, but it's how I code, and I'm not the only one. It is
also worth noting that the more member variables a class owns, the more
potential exists for such bugs to occur.)
Oct 27 '08 #18
On 2008-10-27 16:30:13 -0400, Juha Nieminen <no****@thanks.invalidsaid:
One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget.
Testing will catch that.
If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatically copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)
So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 27 '08 #19
On 2008-10-27 19:29, Jeff Schwab wrote:
Juha Nieminen wrote:
>Ian Collins wrote:
>>I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?

Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.

That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopyable is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?

--
Erik Wikström
Oct 27 '08 #20
Erik Wikström wrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
>Juha Nieminen wrote:
>>Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.

Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopyable is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used since the
epoch of C++.

I don't consider it to be a hack, but an aid to documentation. The
reader can tell at a glance that the class isn't copyable. It also
saves typing!

--
Ian Collins
Oct 27 '08 #21
Pete Becker wrote:
>If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatically copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)

So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?
No, you first call the compiler-generated copy constructor, and then
you copy the special members appropriately.

For example, if you had, let's say, a pointer to a dynamically
allocated object, the compiler-generated copy constructor would simply
copy the value of the pointer, so the copy would point to the same
dynamically allocated object. However, that doesn't matter: Once it has
done that, you simply make a deep copy of the object (or whatever) and
make the pointer point to that new object.

The idea is that you only need to write this special copying code for
that one pointer, and you don't need to write anything for any of the
other member variables (because those are handled by the
compiler-generated copy constructor).
Oct 27 '08 #22
Ian Collins wrote:
Erik Wikström wrote:
>On 2008-10-27 19:29, Jeff Schwab wrote:
>>Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "= delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom. If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopyable is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used since the
epoch of C++.

I don't consider it to be a hack, but an aid to documentation. The
reader can tell at a glance that the class isn't copyable. It also
saves typing!
Agreed. It's self-documenting, and doesn't require the reader to be
familiar with yet another language feature.
Oct 27 '08 #23
On 2008-10-27 18:03:07 -0400, Juha Nieminen <no****@thanks.invalidsaid:
Pete Becker wrote:
>>If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatically copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)

So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?

No, you first call the compiler-generated copy constructor, and then
you copy the special members appropriately.
Okay, you copy the special members twice.

--
Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
Standard C++ Library Extensions: a Tutorial and Reference
(www.petebecker.com/tr1book)

Oct 27 '08 #24
Jeff Schwab wrote:
> One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget.

You have a reasonable point, but IMO such a class is already responsible
for too many things. If a member requires special handling during
copying, then it can be wrapped in a class whose copy constructor does
the right thing. That special handling should be the wrapper's only
job.
That's a reasonable design. On one hand it simplifies the outer class,
because you don't have to write a copy constructor for the entire class.
On the other hand it adds a small layer of complexity to that special
member. For example assume you have something like this:

class MyClass
{
std::list<ObjectobjectList;
std::list<Object>::iterator currentObject;
...
};

Let's assume the specification of this code is that 'currentObject'
always points to either an object inside 'objectList', or to
objectList.end().

This class requires a copy constructor and assignment operator if
instances of this class must be copyable. The copy constructor and
assignment operator need to make 'currentObject' to point to the copied
list (rather than the original).

By your suggested design both 'objectList' and 'currentObject' need to
be wrapped inside an inner class if we want to avoid having to write a
copy constructor and assignment operator on the outer class, so it would
become something like:
class MyClass
{
struct ObjectList
{
std::list<ObjectobjectList;
std::list<Object>::iterator currentObject;

ObjectList(const ObjectList&); // Implement these appropriately
ObjectList& operator=(const ObjectList&);
};

ObjectList objectList;
...
};

Now accessing the 'objectList' member has to always be done with a
"objectList.objectList" (or whatever we want to call the struct
instantiation). Well, I suppose that's a small price to pay for not
having to write a copy constructor and assignment operator for the outer
class...
Oct 27 '08 #25
Pete Becker wrote:
Okay, you copy the special members twice.
Basically yes. The alternative is the current one: You have to copy
everything explicitly.
Oct 27 '08 #26
On Oct 27, 2:05 am, Pete Becker <p...@versatilecoding.comwrote:
On 2008-10-26 17:37:53 -0400, Ian Collins <ian-n...@hotmail.comsaid:
Pete Becker wrote:
On 2008-10-25 21:55:54 -0400, Victor Bazarov
<v.Abaza...@comAcast.netsaid:
>Juha Nieminen wrote:
Marcel Müller wrote:
is there a way to avoid the automatic copy constructor
generation.
>>Yes: Implement your own copy constructor. That will make
the compiler to not to create a default one.
>You don't have to implement it. Just declare one. If
your program does not use it, you don't have to define it.
And to make sure the program does not use it, declare it
'private'.
And a note for the future: with C++0X you don't need to
declare it private.
class C
{
public:
C(const C&) = delete;
};
The "= delete" says that it doesn't exist. There's also "=
default", to tell the compiler to generate the default
version even if it wouldn't otherwise. These also apply to
default constructors, generated assignment operators, etc.
I can see the benefit of "= default", but what benefits does
"= delete" offer over private constructors?
A bit of clarity. A private constructor can be implemented,
and used by members and friends. "= delete" says it doesn't
exist.
And can't be used even by members and friends.

Not a big thing, but the fact that you cannot copy an object is
part of the public interface. So the fact that you explicitly
say so should logically appear in the public part of the class
definition.

--
James Kanze (GABI Software) email:ja*********@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
Oct 28 '08 #27
In message <Ga***************@read4.inet.fi>, Juha Nieminen
<no****@thanks.invalidwrites
>Pete Becker wrote:
>Okay, you copy the special members twice.

Basically yes. The alternative is the current one: You have to copy
everything explicitly.
How do you handle reference members?

--
Richard Herring
Oct 28 '08 #28
On Oct 27, 10:20 pm, Erik Wikström <Erik-wikst...@telia.comwrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits
does "= delete" offer over private constructors?
Declaring a constructor private is more a hack than a clean
idiom. If you accidentally call the copy constructor from
the class itself, you will not get a clean compiler error,
but an obscure linker error, which is not really the best
possible solution.
That's true if the private constructors are declared
directly in the non-copyable class. I wonder whether
=delete offers anything over EBO/inheritance-based utilities
like boost::noncopyable.
Elegance and simplicity. A private copy-constructor is a hack
but boost::noncopyable is much worse, a complex solution to a
simple problem. Why should I have to inherit from some other
class just to make my class non-copyable?
Documentation. Inheritance defines an isA relationship. Your
class isA UncopiableObject.

--
James Kanze (GABI Software) email:ja*********@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
Oct 28 '08 #29
On Oct 27, 11:03 pm, Jeff Schwab <j...@schwabcenter.comwrote:
Ian Collins wrote:
Erik Wikström wrote:
On 2008-10-27 19:29, Jeff Schwab wrote:
Juha Nieminen wrote:
Ian Collins wrote:
I can see the benefit of "= default", but what benefits does "=delete"
offer over private constructors?
Declaring a constructor private is more a hack than a clean idiom.If
you accidentally call the copy constructor from the class itself, you
will not get a clean compiler error, but an obscure linker error, which
is not really the best possible solution.
That's true if the private constructors are declared directly in the
non-copyable class. I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopyable is much worse, a complex solution to a simple
problem. Why should I have to inherit from some other class just to make
my class non-copyable?
It may be a hack, but it's an idiomatic one that's been used
since the epoch of C++.
I don't consider it to be a hack, but an aid to
documentation. The reader can tell at a glance that the
class isn't copyable. It also saves typing!
Agreed. It's self-documenting, and doesn't require the reader
to be familiar with yet another language feature.
Yes and no. I used the techique back in the early 1990's. I
dropped it for awhile because readers weren't familiar with it.
The private copy constructor was the standard idiom, which they
immediately recognized, where as they didn't know what
UncopiableObject did; at the time, at least, it didn't occur to
them that a base class might have not direct interface, and they
expected something more. Thanks to things like std::iterator<>,
std::unary_function<>, etc., modern C++ programmers are far more
open about this, and when they see a class called
UncopiableObject, they don't expect anything more than that it
can't be copied. Some I've reverted to doing things the way I
did 25 years ago.

--
James Kanze (GABI Software) email:ja*********@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
Oct 28 '08 #30
>>>On 2008-10-27 19:29, Jeff Schwab wrote:
>>>>I wonder whether =delete offers anything over
EBO/inheritance-based utilities like boost::noncopyable.
>>Erik Wikström wrote:
Elegance and simplicity. A private copy-constructor is a hack but
boost::noncopyable is much worse
>Ian Collins wrote:
>>I don't consider it to be a hack, but an aid to
documentation. The reader can tell at a glance that the
class isn't copyable.
James Kanze wrote:
Yes and no. I used the techique back in the early 1990's. I
dropped it for awhile because readers weren't familiar with it.
modern C++ programmers are far more
open about this, and when they see a class called
UncopiableObject, they don't expect anything more than that it
can't be copied. Some I've reverted to doing things the way I
did 25 years ago.
If only most "modern C++ programmers" were familiar with "modern C++"!
It seems like things catch on slowly in some quarters. There's still a
lot of C++ code being written as though the past ten years hadn't
happened. I looked at the Mozilla guidelines for portable C++ the other
day, and thought I had fallen into some kind of time warp. OTOH,
UncopiableObject should be at least as clear to such developers as
=delete will be.
Oct 28 '08 #31
On 27 Okt., 22:10, Pete Becker <p...@versatilecoding.comwrote:
On 2008-10-27 16:30:13 -0400, Juha Nieminen <nos...@thanks.invalidsaid:
* One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to your
class, you have to remember to add it to the copy constructor (and
assignment operator). This is extremely easy to forget.

Testing will catch that.
Well - i certainly hope so ;-)
>
If the member
variable is just eg. an int, then it the default copying would be enough
for it, so calling the compiler-generated copy constructor would
automatically copy it without having to do anything special about it.
(The user-written copy constructor could then simply concentrate on the
members which do need special copying.)

So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?
I agree - that would not be possible. But can I sidestep a little and
be off-topic for a second? I really like the idea of having a copy-
constructor being default being defined explicitly with the new
syntax, and now I wonder if there has been any proposal to expand on
the default stuff, notable for swap.
As the user-defined copy-constructor really is error-prone (I have
been bitten once or twice by forgetting the copying when adding a new
member to a class), I do my best to make sure that the default
constructor (and assignment-operator) works and normally restrict my
userdefined constructors to small classes with less than a handfull of
membervariables. But swap is another matter: I normally don't write a
swap function and live with the lost performance, correcting the
problem when e.g. I wind up with sorting large arrays of those
objects. But wouldn't it be nice if you could write void
swap(my_class& other) = default as well?
In other words: has there been any proposal to provide this
functionality in some later version of C++? I have skimmed the docs
but found nothing like that in C++0x. I do not know how general it
could be: having "= default" creating a function with standard
functionality for each member-variable (causing an error when that
functionality is not available) would be nice indeed.

/Peter
Oct 28 '08 #32
Richard Herring wrote:
In message <Ga***************@read4.inet.fi>, Juha Nieminen
<no****@thanks.invalidwrites
>Pete Becker wrote:
>>Okay, you copy the special members twice.

Basically yes. The alternative is the current one: You have to copy
everything explicitly.

How do you handle reference members?
In the exact same way as currently?
Oct 28 '08 #33
peter koch wrote:
On 27 Okt., 22:10, Pete Becker <p...@versatilecoding.comwrote:
>On 2008-10-27 16:30:13 -0400, Juha Nieminen
<nos...@thanks.invalidsaid:
>>One problem with copy constructors (if you have implemented one
explicitly) is that each time you add a new member variable to
your class, you have to remember to add it to the copy
constructor (and assignment operator). This is extremely easy to
forget.

Testing will catch that.

Well - i certainly hope so ;-)
>>
>>If the member
variable is just eg. an int, then it the default copying would be
enough for it, so calling the compiler-generated copy constructor
would automatically copy it without having to do anything special
about it. (The user-written copy constructor could then simply
concentrate on the members which do need special copying.)

So the default copy constructor would only copy members that were
not copied by the user-written one? How could it know?

I agree - that would not be possible. But can I sidestep a little
and be off-topic for a second? I really like the idea of having a
copy- constructor being default being defined explicitly with the
new syntax, and now I wonder if there has been any proposal to
expand on the default stuff, notable for swap.
As the user-defined copy-constructor really is error-prone (I have
been bitten once or twice by forgetting the copying when adding a
new member to a class), I do my best to make sure that the default
constructor (and assignment-operator) works and normally restrict my
userdefined constructors to small classes with less than a handfull
of membervariables. But swap is another matter: I normally don't
write a swap function and live with the lost performance,
correcting the problem when e.g. I wind up with sorting large
arrays of those objects. But wouldn't it be nice if you could
write void swap(my_class& other) = default as well?
In other words: has there been any proposal to provide this
functionality in some later version of C++? I have skimmed the docs
but found nothing like that in C++0x. I do not know how general it
could be: having "= default" creating a function with standard
functionality for each member-variable (causing an error when that
functionality is not available) would be nice indeed.
No, I haven't seen anything like that either.

On the other hand, the standard swap function will attempt a
move-construction of your objects, instead of a copy-construction and
destruction of a temporary. That might improve things enough that you
need fewer specialized swaps.
Bo Persson


Oct 28 '08 #34
peter koch wrote:
>So the default copy constructor would only copy members that were not
copied by the user-written one? How could it know?

I agree - that would not be possible.
And not what I suggested in the first place.
Oct 28 '08 #35

This discussion thread is closed

Replies have been disabled for this discussion.

By using this site, you agree to our Privacy Policy and Terms of Use.