Velocity Reviews

Velocity Reviews (http://www.velocityreviews.com/forums/index.php)
-   C++ (http://www.velocityreviews.com/forums/f39-c.html)
-   -   template copy constructor vs normal copy constructor (http://www.velocityreviews.com/forums/t734148-template-copy-constructor-vs-normal-copy-constructor.html)

cinsk 09-26-2010 03:22 PM

template copy constructor vs normal copy constructor
 
hi.

I just read the definition of the std::pair in <utility>. std::pair
has following two copy constructors:

template <class T1, class T2>
struct pair {

pair::pair(const pair &);

template<class U1, class U2> pair::pair(const pair<U1, U2> &);
...
};

The definition of both copy constructor looks same in my gentoo Linux/
gcc 4.4.3.

Although I'm not good at template, both copy constructors look same to
me.

Q1. What is the purpose of the second copy constructor?
Could you give me some short example code that actually calls
the second copy constructor?

Q2. What happen if the second copy construct is missing?

Q3. How can the compiler determine which copy constructor is used?
In my poor understanding, it looks like that compile would
complain for the ambiguity.

Q4. If I want to make a template class, do I need to provide both copy
constructor?
If not, which is better? And why?

Thank you.

Kai-Uwe Bux 09-26-2010 03:30 PM

Re: template copy constructor vs normal copy constructor
 
cinsk wrote:

> hi.
>
> I just read the definition of the std::pair in <utility>. std::pair
> has following two copy constructors:
>
> template <class T1, class T2>
> struct pair {
>
> pair::pair(const pair &);
>
> template<class U1, class U2> pair::pair(const pair<U1, U2> &);
> ...
> };
>
> The definition of both copy constructor looks same in my gentoo Linux/
> gcc 4.4.3.
>
> Although I'm not good at template, both copy constructors look same to
> me.
>
> Q1. What is the purpose of the second copy constructor?
> Could you give me some short example code that actually calls
> the second copy constructor?


It allows to copy construct a std::pair<double,double> from a
std::pair<int,int>.

> Q2. What happen if the second copy construct is missing?


The above would not be possible

> Q3. How can the compiler determine which copy constructor is used?
> In my poor understanding, it looks like that compile would
> complain for the ambiguity.


The ambiguity you worry about arises as copy-constructing std::pair<int,int>
from std::pair<int,int> matches both. That is true. In that case, overload
resolution kicks in. In this case, the ambiguity is resolved in favor of the
non-templated constructor.

> Q4. If I want to make a template class, do I need to provide both copy
> constructor?
> If not, which is better? And why?


Unless you have the situation where you want a Foo<T> to be copy-
constructible from Foo<S>, you should just go with the first.


Best

Kai-Uwe Bux

cinsk 09-26-2010 04:12 PM

Re: template copy constructor vs normal copy constructor
 
On Sep 27, 12:30*am, Kai-Uwe Bux <jkherci...@gmx.net> wrote:
> cinsk wrote:
> > hi.

>
> > I just read the definition of the std::pair in <utility>. *std::pair
> > has following two copy constructors:

>
> > template <class T1, class T2>
> > struct pair {

>
> > * pair::pair(const pair &);

>
> > * template<class U1, class U2> pair::pair(const pair<U1, U2> &);
> > * ...
> > };

>
> > The definition of both copy constructor looks same in my gentoo Linux/
> > gcc 4.4.3.

>
> > Although I'm not good at template, both copy constructors look same to
> > me.

>
> > Q1. What is the purpose of the second copy constructor?
> > * * * Could you give me some short example code that actually calls
> > the second copy constructor?

>
> It allows to copy construct a std::pair<double,double> from a
> std::pair<int,int>.
>
> > Q2. What happen if the second copy construct is missing?

>
> The above would not be possible
>
> > Q3. How can the compiler determine which copy constructor is used?
> > * * * In my poor understanding, it looks like that compile would
> > complain for the ambiguity.

>
> The ambiguity you worry about arises as copy-constructing std::pair<int,int>
> from std::pair<int,int> matches both. That is true. In that case, overload
> resolution kicks in. In this case, the ambiguity is resolved in favor of the
> non-templated constructor.
>
> > Q4. If I want to make a template class, do I need to provide both copy
> > constructor?
> > * * * If not, which is better? And why?

>
> Unless you have the situation where you want a Foo<T> to be copy-
> constructible from Foo<S>, you should just go with the first.
>
> Best
>
> Kai-Uwe Bux


Thank you for the kind answers!

Regards,

Juha Nieminen 09-26-2010 06:50 PM

Re: template copy constructor vs normal copy constructor
 
Kai-Uwe Bux <jkherciueh@gmx.net> wrote:
>> pair::pair(const pair &);
>>
>> template<class U1, class U2> pair::pair(const pair<U1, U2> &);

>
> It allows to copy construct a std::pair<double,double> from a
> std::pair<int,int>.


Of course this could raise the question of why that *first* copy
constructor is necessary at all, then (because wouldn't the second
one cover also the case where the types are the same)?

IIRC there was some kind of special rule about constructors and
templates in play here. Could someone refresh my memory?

Bo Persson 09-26-2010 06:57 PM

Re: template copy constructor vs normal copy constructor
 
Juha Nieminen wrote:
> Kai-Uwe Bux <jkherciueh@gmx.net> wrote:
>>> pair::pair(const pair &);
>>>
>>> template<class U1, class U2> pair::pair(const pair<U1, U2> &);

>>
>> It allows to copy construct a std::pair<double,double> from a
>> std::pair<int,int>.

>
> Of course this could raise the question of why that *first* copy
> constructor is necessary at all, then (because wouldn't the second
> one cover also the case where the types are the same)?
>
> IIRC there was some kind of special rule about constructors and
> templates in play here. Could someone refresh my memory?


Yes, the first constructor is a copy constructor, the second one is a
converting constructor.

12.8 says that a template is never a copy constructor.


Bo Persson



Juha Nieminen 09-26-2010 07:24 PM

Re: template copy constructor vs normal copy constructor
 
Bo Persson <bop@gmb.dk> wrote:
> 12.8 says that a template is never a copy constructor.


What is the rationale for that rule?

Armen Tsirunyan 09-26-2010 07:32 PM

Re: template copy constructor vs normal copy constructor
 
On Sep 27, 12:24*am, Juha Nieminen <nos...@thanks.invalid> wrote:
> Bo Persson <b...@gmb.dk> wrote:
> > 12.8 says that a template is never a copy constructor.

>
> * What is the rationale for that rule?


I am not an expert, but I'll give it a try. Maybe because the copy
constructor is ALWAYS declared, and the declaration is not a template
one?

Johannes Schaub (litb) 09-27-2010 02:00 PM

Re: template copy constructor vs normal copy constructor
 
Juha Nieminen wrote:

> Bo Persson <bop@gmb.dk> wrote:
>> §12.8 says that a template is never a copy constructor.

>
> What is the rationale for that rule?


In C++03, there appears to be no way to declare a copy constructor even if
that rule were absent. This is because you need the first parameter to be
based on the current class type. But if it includes template parameters of
itself, this can never be the case:

struct A {
template<typename T>
A(... /* where to put T!? */);
};

In C++0x this is possible by just using default arguments

struct A {
template<typename T = int>
A(A const&);
};

So the actual reason might be that a template is not really a function. It's
a template that first need to be instantiated.

There is another rule that a template cannot be used to instantiate a copy
constructor. But that rule's history is quite amusing. I have seen people in
here argue about it and its desired meaning, but it appears it's very
simple: http://www.open-std.org/jtc1/sc22/wg...tive.html#1080 .

James Kanze 09-27-2010 04:48 PM

Re: template copy constructor vs normal copy constructor
 
On Sep 27, 3:00 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
wrote:
> Juha Nieminen wrote:
> > Bo Persson <b...@gmb.dk> wrote:
> >> 12.8 says that a template is never a copy constructor.


> > What is the rationale for that rule?


> In C++03, there appears to be no way to declare a copy
> constructor even if that rule were absent. This is because you
> need the first parameter to be based on the current class
> type. But if it includes template parameters of itself, this
> can never be the case:


> struct A {
> template<typename T>
> A(... /* where to put T!? */);
> };


> In C++0x this is possible by just using default arguments


> struct A {
> template<typename T = int>
> A(A const&);
> };


> So the actual reason might be that a template is not really
> a function. It's a template that first need to be
> instantiated.


> There is another rule that a template cannot be used to
> instantiate a copy constructor. But that rule's history is
> quite amusing. I have seen people in here argue about it and
> its desired meaning, but it appears it's very
> simple:http://www.open-std.org/jtc1/sc22/wg...tive.html#1080.


It's not that simple, because when copying an object, normal
overload resolution is done. The "copy constructor" has no
priviledged role. What is important is that a template function
cannot ever be a copy constructor, which means that it won't
prevent the compiler from generating one, e.g.:

struct A
{
template<typename T>
A(T const& other) { std::cout << "Copying" << std::endl; }
};

int
main()
{
A a;
A b(a);
return 0;
}

will output nothing (since the compiler generated copy
constructor is an equally good match as the template, and when
two functions are otherwise equally good matches, the
non-template wins). Drop the const in the signature of the
constructor template, and the template will win, since it is
a better match. (The compiler generated copy constructor will
still be generated, and be used when copying a temporary.)

Of course, if the compiler generated copy constructor doesn't do
what you want, you'll have to define one in addition to the
templated one, or you'll spend a lot of time tracking down
obscure errors.

--
James Kanze


Johannes Schaub (litb) 09-27-2010 06:20 PM

Re: template copy constructor vs normal copy constructor
 
James Kanze wrote:

> On Sep 27, 3:00 pm, "Johannes Schaub (litb)" <schaub-johan...@web.de>
> wrote:
>> Juha Nieminen wrote:
>> > Bo Persson <b...@gmb.dk> wrote:
>> >> §12.8 says that a template is never a copy constructor.

>
>> > What is the rationale for that rule?

>
>> In C++03, there appears to be no way to declare a copy
>> constructor even if that rule were absent. This is because you
>> need the first parameter to be based on the current class
>> type. But if it includes template parameters of itself, this
>> can never be the case:

>
>> struct A {
>> template<typename T>
>> A(... /* where to put T!? */);
>> };

>
>> In C++0x this is possible by just using default arguments

>
>> struct A {
>> template<typename T = int>
>> A(A const&);
>> };

>
>> So the actual reason might be that a template is not really
>> a function. It's a template that first need to be
>> instantiated.

>
>> There is another rule that a template cannot be used to
>> instantiate a copy constructor. But that rule's history is
>> quite amusing. I have seen people in here argue about it and
>> its desired meaning, but it appears it's very
>> simple:http://www.open-std.org/jtc1/sc22/wg...tive.html#1080.

>
> It's not that simple, because when copying an object, normal
> overload resolution is done. The "copy constructor" has no
> priviledged role. What is important is that a template function
> cannot ever be a copy constructor, which means that it won't
> prevent the compiler from generating one, e.g.:
>


That's clear anyway because only a non-template constructor can be a copy
constructor. What I meant is that people disagreed on what that statement
means to never instantiate a constructor to do the copy

- Templates are just ignored when doing overload resolution when copying a
class object of type A to another object of type A
- Templates are considered, but if an instantiation is needed the program
either needs to explicitly instantiate the constructor or explicitly
specialize it to provide a suitable specialization.
- Templates are considered, but overload resolution ignores any candidates
for which argument deduction yields a parameter list with "cv T" as type.

The issue was further confused by a footnote that explicitly allowed a
template constructor to be used to copy the object in C++03, and that note
was removed from the C++0x draft. And now they get to it again and see they
shouldn't had removed that footnote.




All times are GMT. The time now is 10:09 AM.

Powered by vBulletin®. Copyright ©2000 - 2014, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.