copy ctor and 'explicit' qualifier

S

subramanian100in

I have the following understanding: Please let me know if it is
correct:
copy ctor of a class is NOT declared with 'explicit' qualifier because
if it is declared 'explicit', then the class cannot be used with
standard library container. Is this reasoning correct ? Or is there
some other reason for NOT declaring the copy ctor with 'explicit'
qualifier ?

Kindly clarify.

Thanks
V.Subramanian
 
A

Angus

I have the following understanding: Please let me know if it is
correct:
copy ctor of a class is NOT declared with 'explicit' qualifier because
if it is declared 'explicit', then the class cannot be used with
standard library container. Is this reasoning correct ? Or is there
some other reason for NOT declaring the copy ctor with 'explicit'
qualifier ?

Kindly clarify.

Thanks
V.Subramanian

I don't think that is correct.

if you declare a single arguement constructor then this implies an
implicit assignment. For example:

class MyClass
{
MyClass(int amount) : m_amount(amount){}

You can now do this:

MyClass mc = 3;

In the above example that conversion may be ok. But there will be
some cases where you do not want this implicit conversion to take
place. ie you want to prevent MyClass mc = 3; That is when you
decalre the constructor explicit.

ie

explicit MyClass(int amount) : m_amount(amount){}

Now MyClass mc = 3; won't compile.

you will see an error like this:
error C2440: 'initializing' : cannot convert from 'const int' to
'class MyClass'
No constructor could take the source type, or constructor
overload resolution was ambiguous

There may be particular reasons why you using explicit with a
container causes your program not to compile. Perhaps if you post
some code we can have a look at what you are doing.
 
J

James Kanze

I have the following understanding: Please let me know if it is
correct:
copy ctor of a class is NOT declared with 'explicit' qualifier
because if it is declared 'explicit', then the class cannot be
used with standard library container. Is this reasoning
correct ?

Only partially. Basically, if the copy constructor is explicit,
then it can only be used in contexts in which the constructor is
considered to have been explicitly called, e.g. explicit
conversions (any of the different cast notations), or direct
initialization (but not copy initialization---which means that
they cannot be passed by value as arguments to a function, nor
returned by value from a function).
Or is there some other reason for NOT declaring the copy ctor
with 'explicit' qualifier ?

I'd say that the principal reason is that it isn't clear what it
means to declare a copy constructor "explicit". At least to me,
it creates confusion as to what was actually desired. It seems
to be a way of saying that an object supports copy, but not
always.
 
A

abir

Only partially. Basically, if the copy constructor is explicit,
then it can only be used in contexts in which the constructor is
considered to have been explicitly called, e.g. explicit
conversions (any of the different cast notations), or direct
initialization (but not copy initialization---which means that
they cannot be passed by value as arguments to a function, nor
returned by value from a function).


I'd say that the principal reason is that it isn't clear what it
means to declare a copy constructor "explicit". At least to me,
it creates confusion as to what was actually desired. It seems
to be a way of saying that an object supports copy, but not
always.

--
James Kanze (GABI Software) email:[email protected]
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

I use explicit copy-ctor sometimes to prevent some new programmer (esp
from matlab domain, where cow is the common mode of copying) to copy
class unnecessarily.
class BigClass{
public:
BigClass(){}
explicit BigClass(const BigClass& c){}
};
class BigClassLender{
private:
BigClass bigClass_;
public:
const BigClass& get()const{ return bigClass_;}
};
BigClassLender lender;
BigClass c = lender.get(); /// WOW, he wanted const BigClass& c =
lender.get() actually.
Now with explicit copy ctor, he have to write BigClass
c(lender.get()); if he really want's copy.
so it is just preventive measurement for the guys who usually works
with ref symantica, and suddenly comes to c++ value world!
reference is good as function argument as it silently passes a value
type as reference (on contrary to pointer) , it is bad as return
argument as it silently converts to value from reference type.

thanks
abir
 
J

James Kanze

On Mar 31, 4:28 pm, James Kanze <[email protected]> wrote:
I use explicit copy-ctor sometimes to prevent some new
programmer (esp from matlab domain, where cow is the common
mode of copying) to copy class unnecessarily.

If you don't want to support copy, just declare the copy
constructor private, and don't implement it. That's the
standard solution.
 
A

Andrey Tarasevich

copy ctor of a class is NOT declared with 'explicit' qualifier because
if it is declared 'explicit', then the class cannot be used with
standard library container. Is this reasoning correct ? Or is there
some other reason for NOT declaring the copy ctor with 'explicit'
qualifier ?

Declaring the copy-constructor 'explicit' will essentially prevent any
form of copy-initialization, because the copying in the
copy-initialization is always implicit. (Maybe I'm missing something,
but right away I can't think of any way to express copy-construction in
copy-initialization _explicitly_).

This means that it will become impossible to copy-initialize objects of
this class (regardless of whether the initialization requires a
conversion), pass these objects to functions (pass "by value" that is),
return them from functions, throw them as exceptions etc.

At the same the copy-constructor will still work in
direct-initialization contexts.

I wouldn't say that declaring the copy-constructor 'explicit' will make
it unusable with STL containers. The 'CopyConstructible' requirement
imposed on the container element type is expressed in terms of
direct-initialization, which should not be affected by 'explicit'
(assuming that the container implementation is done correctly). The only
thing that will be disabled by this is the default argument support for
those container member functions that use them.
 
A

abir

If you don't want to support copy, just declare the copy
constructor private, and don't implement it. That's the
standard solution.

--
James Kanze (GABI Software) email:[email protected]
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

If i don't want to support copy, i disable it. But if i want to
prevent misuse of copy (esp for programmers who usually work with
reference semantics) , i sometimes make copy ctor explicit, or use
move semantic.
again saying, explicit copy ctor is just informing the coder/user
that they are doing something _unconventional_ with the const
reference return type and should check their code once, nothing more
than that.

abir
 
J

James Kanze

Declaring the copy-constructor 'explicit' will essentially
prevent any form of copy-initialization, because the copying
in the copy-initialization is always implicit. (Maybe I'm
missing something, but right away I can't think of any way to
express copy-construction in copy-initialization
_explicitly_).

To tell the truth, logically, I would think that using
copy-initialization is saying explicitly that I want a copy.
The standard, however, says quite explicitly: "An explicit
constructor constructs objects just like non-explicit
constructors, but does so only where the direct-initialization
syntax or where casts are explicitly used." So if T has an
explicit copy constructor, and u is an object of type T:
T t( u ) ; // legal
T t = u ; // illegal
despite the fact that in §8.5 it says that if the types are the
same, copy initialization and direct initialization have the
same semantics.
This means that it will become impossible to copy-initialize
objects of this class (regardless of whether the
initialization requires a conversion), pass these objects to
functions (pass "by value" that is), return them from
functions, throw them as exceptions etc.
At the same the copy-constructor will still work in
direct-initialization contexts.
I wouldn't say that declaring the copy-constructor 'explicit'
will make it unusable with STL containers. The
'CopyConstructible' requirement imposed on the container
element type is expressed in terms of direct-initialization,
which should not be affected by 'explicit' (assuming that the
container implementation is done correctly). The only thing
that will be disabled by this is the default argument support
for those container member functions that use them.

That's true today, but the latest draft for the next version
says specifies:
T t = u ;
as a requirement for CopyConstructible, which means that the
copy constructor cannot be explicit.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

explicit ctor in vector 5
copy ctor being private and compilation error 6
default ctor 17
copy ctor 3
copy ctor vs default ctor 2
inline and ctor 12
why copy ctor not called 15
conversion operator and conversion ctor 2

Members online

No members online now.

Forum statistics

Threads
474,262
Messages
2,571,056
Members
48,769
Latest member
Clifft

Latest Threads

Top