Explicit copy constructor

  • Thread starter Christoph Bartoschek
  • Start date
C

Christoph Bartoschek

Hi,

gcc 3.4 rejects the following program:

class T {
public:
T() : a(3) {}
explicit T(T const & other) : a(other.a) {}
private:
int a;
};

void func(T const & obj) {
}

int main() {
func(T());
}

The error is:

no matching function for call to `T::T(const T&)'

There is some reasoning about it at:

http://gcc.gnu.org/bugs.html#cxx_rvalbind

This seems to be correct for private copy constructors, but I am not sure
whether the interpretation by the gcc team also applies to explicit copy
constructors. Is there some discussion about the correct interpretation of
the standard for explicit copy constructors?

Christoph Bartoschek
 
V

Victor Bazarov

Christoph Bartoschek said:
Hi,

gcc 3.4 rejects the following program:

class T {
public:
T() : a(3) {}
explicit T(T const & other) : a(other.a) {}
private:
int a;
};

void func(T const & obj) {
}

int main() {
func(T());
}

The error is:

no matching function for call to `T::T(const T&)'

There is some reasoning about it at:

http://gcc.gnu.org/bugs.html#cxx_rvalbind

This seems to be correct for private copy constructors, but I am not sure
whether the interpretation by the gcc team also applies to explicit copy
constructors. Is there some discussion about the correct interpretation of
the standard for explicit copy constructors?

Explicit constructor requires the direct initialiser syntax or
an explicit cast. Creation of a temporary from an r-value for
binding a temporary (even if it's not done that way) is all
implicit. It seems that if copy-constructor is declared explicit
would prevent a temporary object from initialising (since no
syntax can be used for that).

Why would you want to have the copy c-tor explicit?

Victor
 
D

Dave Moore

Christoph Bartoschek said:
Hi,

gcc 3.4 rejects the following program:

class T {
public:
T() : a(3) {}
explicit T(T const & other) : a(other.a) {}
private:
int a;
};

void func(T const & obj) {
}

int main() {
func(T());
}

The error is:

no matching function for call to `T::T(const T&)'

There is some reasoning about it at:

http://gcc.gnu.org/bugs.html#cxx_rvalbind

This seems to be correct for private copy constructors, but I am not sure
whether the interpretation by the gcc team also applies to explicit copy
constructors. Is there some discussion about the correct interpretation of
the standard for explicit copy constructors?

Christoph Bartoschek

The whole point of declaring a constructor explicit is that it can
only be called *explicitly*:

T apple;
T orange(apple);

Your code is generating an *implicit* copy constructor call, thus the
behavior makes sense using the logic laid out in the gcc document.
Specifically, the proper semantics for the copy constructor call are
not being obeyed in your case since the copy constructor is being
called implicitly.

HTH, Dave Moore

P.S. Why do you want an explicit copy constructor?
 
D

DaKoadMunky

class T {
public:
T() : a(3) {}
explicit T(T const & other) : a(other.a) {}
private:
int a;
};

void func(T const & obj) {
}

int main() {
func(T());
}

I don't understand how the error is being generated.

Where is a copy-constructor being called implicitly in this code?

What am I missing?

I can tell you that this code compiled at www.comeaucomputing.com using their
online compiler.
 
M

Michiel Salters

Christoph Bartoschek said:
Hi,

gcc 3.4 rejects the following program:

class T {
public:
T() : a(3) {}
explicit T(T const & other) : a(other.a) {}
private:
int a;
};

void func(T const & obj) {
}

int main() {
func(T());
}

The error is:

no matching function for call to `T::T(const T&)'

There is some reasoning about it at:

http://gcc.gnu.org/bugs.html#cxx_rvalbind

This seems to be correct for private copy constructors, but I am not sure
whether the interpretation by the gcc team also applies to explicit copy
constructors. Is there some discussion about the correct interpretation of
the standard for explicit copy constructors?

Yes, CWG issue 152. It changed between C++98 and C++03.

The new rules are:

When objects of class type are direct-initialized (8.5 dcl.init), or
copy-initialized from an expression of the same or a derived class
type (8.5 dcl.init), overload resolution selects the constructor. For
direct-initialization, the candidate functions are all the
constructors of the class of the object being initialized. For
copy-initialization, the candidate functions are all the converting
constructors (12.3.1 class.conv.ctor ) of that class.

A non-explicit copy constructor (12.8 class.copy) is a converting
constructor.

This form requires copy-initialization to copy the temporary to the
bound argument (although the actual copy may be optimized out). In
this case, there's no converting ctor available.

Regards,
Michiel Salters
 
C

Christoph Bartoschek

Victor Bazarov wrote:

....
Why would you want to have the copy c-tor explicit?

This was not my decision. But:

We have a a class Node which is can be copied and used as a POD. However the
addresses of objects of Node are used as indexes for the interface of the
underlying C subsystem. 95% of all uses of Node are in conjunction with
this subsystem. Most mistakes when using this system came from constructs
like this:

Node node = bla.get_node();
subsystem_get_parent(handle(node));

It is hard to find such an error. Therefore it was decided, that the copy
constructor of Node becomes explicit to avoid such mistakes. Now each time
one forgets the reference character the compiler complains.

Christoph Bartoschek
 
C

Christoph Bartoschek

Michiel Salters wrote:
....
Yes, CWG issue 152. It changed between C++98 and C++03.

The new rules are:

When objects of class type are direct-initialized (8.5 dcl.init), or
copy-initialized from an expression of the same or a derived class
type (8.5 dcl.init), overload resolution selects the constructor. For
direct-initialization, the candidate functions are all the
constructors of the class of the object being initialized. For
copy-initialization, the candidate functions are all the converting
constructors (12.3.1 class.conv.ctor ) of that class.

A non-explicit copy constructor (12.8 class.copy) is a converting
constructor.

This form requires copy-initialization to copy the temporary to the
bound argument (although the actual copy may be optimized out). In
this case, there's no converting ctor available.

Thanks, this argumentation was convincing.

Christoph Bartoschek
 

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

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top