Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > template copy constructor vs normal copy constructor

Reply
Thread Tools

template copy constructor vs normal copy constructor

 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-09-2010
Blanchet Florian wrote:

> In article <i8pkvg$20r$03$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
> says...
>> It says that a constructor of class X whose first parameter is of type
>> "cv X&" and either there are no other parameters or all other parameters
>> have default arguments, is a copy constructor. This does not apply to the
>> above template, and so it is *not* a copy constructor.
>>

>
> I'm agree with James. It's not a copy constructor because the draft says
> "A non-template constructor for class X is a copy constructor if ..."
> and not only "its first parameter is of type X&,...".
>
> If it was just "its first parameter is of type X&,...", the result of
>
> struct A { template<class T> A(T&){std::cout << 0} };
> int main() { A a; A b(a); return 0; }
>
> would be "0", because the template constructor A<A>(A&) is a constructor
> and is first parameter is of type A&. And the result isn't "0".
>


I keep disagreeing This is allegedly forbidden (by the interpretation of
some people) by another paragraph, namely 12.8/p3 "A member function
template is never instantiated to perform the copy of a class object to an
object of its class type." (See the other post of me where I link to an
issue report about the interpretation of this).

12.8/p2 has nothing to do with it. The stuff you quote from p2 says that a
*non-template* can be a copy constructor - in other words a template cannot
be a copy constructor. A function instantiated from a template is not a
template. So it does entirely not apply, see below.

In addition, nothing says that only copy constructors are allowed to copy an
object. So even if it were like you are saying and "A non-template ..."
makes also the specialization non-copy constructors, that wouldn't change
anything with regard to your example above.

What it makes sure is that the following template declaration does not
inhibit the implicit declaration of a copy constructor

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

If we take out "A non-template" then in C++0x the above will not have an
implicitly declared copy-constructor anymore, because the template will be a
copy constructor. Now I was stating such code is impossible in C++03 anyway
because in C++03 you must arrange for "T" to be deduced from the arguments,
and then you cannot satisfy the conditions for copy constructors anymoe.

Also, there is a destinction between "non-template" and "non-template
function":

- non-template: Anything that is not a template.
- non-template function: Anything that is a function, but is not a function
template specialization.

The first is a natural term which just says "not a template". I can't find
any other non-natural usage of it in the IS. But the latter has special
meaning in the IS: And it's used as if it's the negation of the pre-C++03
"template function" term, and as such excludes function template
specializations as opposed to "non-template".

12.8/p2 says "non-template constructor" so it means:

- Any constructor that is not a template

This includes constructors instantiated from templates, as opposed to
excluding them.
 
Reply With Quote
 
 
 
 
Blanchet Florian
Guest
Posts: n/a
 
      10-09-2010
In article <(E-Mail Removed)>, Leigh
Johnston says...
>
> On 09/10/2010 16:23, Blanchet Florian wrote:
> > would be "0", because the template constructor A<A>(A&) is a constructor
> > and is first parameter is of type A&. And the result isn't "0".

>
> The result is "0" on VC++ and g++. If it was A(const T&) the result
> wouldn't be "0".
>
> /Leigh



Yes, I forgot a const, in "generalized copy constructor" or in
declaration of a. (I would just shows that the default copy constructor
is generated by the compiler)

PS: I forgot a default constructor too.
 
Reply With Quote
 
 
 
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-09-2010
Johannes Schaub (litb) wrote:

> Blanchet Florian wrote:
>
>> In article <i8pkvg$20r$03$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
>> says...
>>> It says that a constructor of class X whose first parameter is of type
>>> "cv X&" and either there are no other parameters or all other parameters
>>> have default arguments, is a copy constructor. This does not apply to
>>> the above template, and so it is *not* a copy constructor.
>>>

>>
>> I'm agree with James. It's not a copy constructor because the draft says
>> "A non-template constructor for class X is a copy constructor if ..."
>> and not only "its first parameter is of type X&,...".
>>
>> If it was just "its first parameter is of type X&,...", the result of
>>
>> struct A { template<class T> A(T&){std::cout << 0} };
>> int main() { A a; A b(a); return 0; }
>>
>> would be "0", because the template constructor A<A>(A&) is a constructor
>> and is first parameter is of type A&. And the result isn't "0".
>>

>
> I keep disagreeing This is allegedly forbidden (by the interpretation of
> some people) by another paragraph, namely 12.8/p3 "A member function
> template is never instantiated to perform the copy of a class object to an
> object of its class type." (See the other post of me where I link to an
> issue report about the interpretation of this).
>
> 12.8/p2 has nothing to do with it. The stuff you quote from p2 says that a
> *non-template* can be a copy constructor - in other words a template
> cannot be a copy constructor. A function instantiated from a template is
> not a template. So it does entirely not apply, see below.
>
> In addition, nothing says that only copy constructors are allowed to copy
> an object. So even if it were like you are saying and "A non-template ..."
> makes also the specialization non-copy constructors, that wouldn't change
> anything with regard to your example above.
>
> What it makes sure is that the following template declaration does not
> inhibit the implicit declaration of a copy constructor
>
> struct A {
> template<typename T = int>
> A(A const&);
> };
>
> If we take out "A non-template" then in C++0x the above will not have an
> implicitly declared copy-constructor anymore, because the template will be
> a copy constructor. Now I was stating such code is impossible in C++03
> anyway because in C++03 you must arrange for "T" to be deduced from the
> arguments, and then you cannot satisfy the conditions for copy
> constructors anymoe.
>


I just see that I miss some very important insight throughout the whole
discussion. The following *is* valid C++03:

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

So, if "A non-template" would be missing, then this would inhibit the
implicitly declared copy constructor too, and the following will be ill-
formed:

A a;
A b = a; // no matching constructor!

So please take this into account when answering. I was overlooking this and
thought "If it can't be deduced, it's illegal" but that of course is not
true at all.
 
Reply With Quote
 
Blanchet Florian
Guest
Posts: n/a
 
      10-09-2010
In article <i8q4ld$52g$03$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
says...

> I keep disagreeing This is allegedly forbidden (by the interpretation

of
> some people) by another paragraph, namely 12.8/p3 "A member function
> template is never instantiated to perform the copy of a class object to an
> object of its class type." (See the other post of me where I link to an
> issue report about the interpretation of this).
>


12.8/p3 is about move-constructor in n3126, and I think gcc repect these
points of the draft. (So "A member function template is never
instantiated to perform the copy of a class object to an object of its
class type." is not true now).

> 12.8/p2 has nothing to do with it. The stuff you quote from p2 says that a
> *non-template* can be a copy constructor - in other words a template cannot
> be a copy constructor. A function instantiated from a template is not a
> template. So it does entirely not apply, see below.


If I'm based on Comeau C++ Template FAQ, A<A>(A&) (or A<A>(const A&)),
is a template function, so is not a non-template function.

> In addition, nothing says that only copy constructors are allowed to copy an
> object. So even if it were like you are saying and "A non-template ..."
> makes also the specialization non-copy constructors, that wouldn't change
> anything with regard to your example above.


Yes, I forgot a const to force to call default copy constructor.

> What it makes sure is that the following template declaration does not
> inhibit the implicit declaration of a copy constructor
>
> struct A {
> template<typename T = int>
> A(A const&);
> };


I'm agrre, because A<T>(A const&) is a template function, so the
compiler have to make a default copy-constructor.

> This includes constructors instantiated from templates, as opposed to
> excluding them.


So, what is exclude ?
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-09-2010
Blanchet Florian wrote:

> In article <i8q4ld$52g$03$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
> says...
>
>> I keep disagreeing This is allegedly forbidden (by the interpretation

> of
>> some people) by another paragraph, namely 12.8/p3 "A member function
>> template is never instantiated to perform the copy of a class object to
>> an object of its class type." (See the other post of me where I link to
>> an issue report about the interpretation of this).
>>

>
> 12.8/p3 is about move-constructor in n3126, and I think gcc repect these
> points of the draft. (So "A member function template is never
> instantiated to perform the copy of a class object to an object of its
> class type." is not true now).
>


I don't understand this.

>> 12.8/p2 has nothing to do with it. The stuff you quote from p2 says that
>> a *non-template* can be a copy constructor - in other words a template
>> cannot be a copy constructor. A function instantiated from a template is
>> not a template. So it does entirely not apply, see below.

>
> If I'm based on Comeau C++ Template FAQ, A<A>(A&) (or A<A>(const A&)),
> is a template function, so is not a non-template function.
>


A constructor is not necessarily a function. It can also be a template. But
you take the term "non-template constructor" and replace it by "non-template
function". These two are not equivalent.

In the IS, it's all about terms and the order they are presented in a
sentence. For example, "int &r;" is an object declaration. But it is not the
declaration of an object.

If "non-template constructor" is intended to mean something else than
"constructor that is not a template", I suggest the wording to be changed to
indicate the real intent. Or to at least put an explanatory note.

>> What it makes sure is that the following template declaration does not
>> inhibit the implicit declaration of a copy constructor
>>
>> struct A {
>> template<typename T = int>
>> A(A const&);
>> };

>
> I'm agrre, because A<T>(A const&) is a template function, so the
> compiler have to make a default copy-constructor.
>


It has nothing to do with template functions (these are called "function
template specializations" in C++03 onwards. The term "template function" is
not used anymore). The reason the above still declares an implicit copy
constructor is that our declared A::A is a template, and templates aren't
copy constructors.

You cannot explicitly declare a function template specialization in the
class definition. The condition for implicit declaration of a copy
constructor is that the class definition does not explicitly declare a copy
constructor, though.

>> This includes constructors instantiated from templates, as opposed to
>> excluding them.

>
> So, what is exclude ?


I don't understand.

 
Reply With Quote
 
Blanchet Florian
Guest
Posts: n/a
 
      10-09-2010
In article <i8q7vn$nq4$02$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
says...
> A constructor is not necessarily a function. It can also be a template. But
> you take the term "non-template constructor" and replace it by "non-template
> function". These two are not equivalent.
>
> In the IS, it's all about terms and the order they are presented in a
> sentence. For example, "int &r;" is an object declaration. But it is not the
> declaration of an object.
>
> If "non-template constructor" is intended to mean something else than
> "constructor that is not a template", I suggest the wording to be changed to
> indicate the real intent. Or to at least put an explanatory note.
>


I know that terms are very important in the IS, but perhap's I
misunderstand the template terms. I'll try to well understand your
messages.

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

template<>
A::A<char>(const A&) {std::cout << 0;}

int main()
{
A a;
A b = a;
system("PAUSE"); return 0;
}

So, (correct if I say wrong things), in this code, A::A<char> is a
template constructor ? And its first parameter is of type const A&, so
it's a copy constructor ? But, when I try this code with gcc there is no
output. It's because this template constructor is declared (and define)
outside A ?
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-09-2010
Blanchet Florian wrote:

> In article <i8q7vn$nq4$02$(E-Mail Removed)-online.com>, Johannes Schaub (litb)
> says...
>> A constructor is not necessarily a function. It can also be a template.
>> But you take the term "non-template constructor" and replace it by
>> "non-template function". These two are not equivalent.
>>
>> In the IS, it's all about terms and the order they are presented in a
>> sentence. For example, "int &r;" is an object declaration. But it is not
>> the declaration of an object.
>>
>> If "non-template constructor" is intended to mean something else than
>> "constructor that is not a template", I suggest the wording to be changed
>> to indicate the real intent. Or to at least put an explanatory note.
>>

>
> I know that terms are very important in the IS, but perhap's I
> misunderstand the template terms. I'll try to well understand your
> messages.
>
> struct A
> {
> A() =default;
> template<typename>
> A(const A&);
> };
>
> template<>
> A::A<char>(const A&) {std::cout << 0;}
>
> int main()
> {
> A a;
> A b = a;
> system("PAUSE"); return 0;
> }
>
> So, (correct if I say wrong things), in this code, A::A<char> is a
> template constructor ?


It is

- A function template specialization. We could call it a template function
since that's the term used by ARM and still by some, but not really by C++03
anymore.
- Not a function template. Therefor, from what the IS says I conclude it is
a "non-template constructor". It's a function, not a template.

The second A::A you declared is

- Not a function template specialization
- A function template. Therefor, from what the IS says I conclude it is a
"non-template constructor". It's a function, not a template.

I have to say I'm not quite sure about the exact meaning of "template
constructor" anymore. A::A<char> definitely is not a template. But likewise
is a "template function" not a template. Still "template" appears in the
term of "template function", but only to say that the function was generated
from / explicitly specified for a template.

I wouldn't want to bet on the exact meaning of "template constructor". I
just think that the "obvious" meaning is "A constructor that is not a
template".

> And its first parameter is of type const A&, so
> it's a copy constructor ?


Yes, using my above explanation I think that the IS says that A::A<char> is
a copy constructor.

> But, when I try this code with gcc there is no
> output. It's because this template constructor is declared (and define)
> outside A ?


No, it is simply because the template cannot be called. How should it deduce
the template parameter of it? You have to give the parameter a default
argument (C++0x) to be able to call it.

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-09-2010
On Oct 9, 12:53 pm, "Johannes Schaub (litb)" <(E-Mail Removed)>
wrote:
> James Kanze wrote:
> > On Oct 8, 11:14 pm, "Johannes Schaub (litb)" <(E-Mail Removed)>
> > wrote:
> >> Juha Nieminen wrote:
> >> > "Johannes Schaub (litb)" <(E-Mail Removed)> wrote:
> >> >> Juha Nieminen wrote:


> >> >>> Bo Persson <(E-Mail Removed)> 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!? */);
> >> >> };


> >> > I don't really understand.


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


> >> No, that template is not a copy constructor because the
> >> parameter is of type "const T&", not "const A&".


> > No. An instantiation of that template (even for A) is not a copy
> > constructor because the standard says that instantiations of
> > templates are never copy constructors. Without this special
> > rule, it would be a copy constructor, because when instantiated
> > with A, its parameter has type A const&.


> It says that a constructor of class X whose first parameter is
> of type "cv X&" and either there are no other parameters or
> all other parameters have default arguments, is a copy
> constructor. This does not apply to the above template, and so
> it is *not* a copy constructor.


The above template isn't even a constructor until its
instantiated. Use a little common sense. The class above has a
constructor, defined by the template, which has a single
parameter of type A const&. Without the special language
excluding templates, it would be a copy constructor.

> If you read what I wrote carefully, you will find I have not
> said anything about an instantiated specialization of it being
> a copy constructor or not. Please read more careful before
> disagreeing.


I'm not disagreeing, the standard is.

--
James Kanze
 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      10-09-2010
On Oct 9, 4:23 pm, Blanchet Florian <(E-Mail Removed)> wrote:
[...]
> If it was just "its first parameter is of type X&,...", the result of


> struct A { template<class T> A(T&){std::cout << 0} };
> int main() { A a; A b(a); return 0; }
>
> would be "0", because the template constructor A<A>(A&) is a
> constructor and is first parameter is of type A&. And the
> result isn't "0".


It should be. The fact that the template is not a copy
constructor means that the compiler will generate one. With the
signature (here): A(T const&). But the template function
remains a better match if the object is a non-const lvalue, as
is the case here, so it gets chosen over the compiler generated
copy constructor.

If the template had the signature A(T const&), this would not be
the case, since both it and the compiler generated constructors
would be equally good matches, and when all other things are
equal, a non-template function wins over a template function.

> Even if it isn't a "strict" copy constructor, it's called
> "generalized copy constructor" by some programmers (like
> Meyers, cf Eff++ Item 45).


It's partially a question of context. In the context of the
standard, the presence of a user defined "copy constructor"
prevents the compiler from generating a default copy
constructor. And that is all "copy constructor" means in the
standard. There is no preference for a copy constructor when
copying, for example; normal overload resolution applies. In
everyday speach, however, it's more or less normal to consider
any constructor which "copies", or which is used to copy, a copy
constructor. This is (I'm fairly sure) what Meyers means by
"generalized copy constructor".

--
James Kanze
 
Reply With Quote
 
Johannes Schaub (litb)
Guest
Posts: n/a
 
      10-09-2010
James Kanze wrote:

> On Oct 9, 12:53 pm, "Johannes Schaub (litb)" <(E-Mail Removed)>
> wrote:
>> James Kanze wrote:
>> > On Oct 8, 11:14 pm, "Johannes Schaub (litb)" <(E-Mail Removed)>
>> > wrote:
>> >> Juha Nieminen wrote:
>> >> > "Johannes Schaub (litb)" <(E-Mail Removed)> wrote:
>> >> >> Juha Nieminen wrote:

>
>> >> >>> Bo Persson <(E-Mail Removed)> 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!? */);
>> >> >> };

>
>> >> > I don't really understand.

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

>
>> >> No, that template is not a copy constructor because the
>> >> parameter is of type "const T&", not "const A&".

>
>> > No. An instantiation of that template (even for A) is not a copy
>> > constructor because the standard says that instantiations of
>> > templates are never copy constructors. Without this special
>> > rule, it would be a copy constructor, because when instantiated
>> > with A, its parameter has type A const&.

>
>> It says that a constructor of class X whose first parameter is
>> of type "cv X&" and either there are no other parameters or
>> all other parameters have default arguments, is a copy
>> constructor. This does not apply to the above template, and so
>> it is *not* a copy constructor.

>
> The above template isn't even a constructor until its
> instantiated. Use a little common sense. The class above has a
> constructor, defined by the template, which has a single
> parameter of type A const&. Without the special language
> excluding templates, it would be a copy constructor.
>


Now you are contradicting yourself: "The above template isn't even a
constructor until its [sic] instantiated." <-> "The class above has a
constructor, defined by the template, [...]".

"The class above has a constructor, defined by the template, which has a
single parameter of type A const&." -> No, the parameter of that function
template is of type "T const&". The types "T const&" and "A const&" are
different. Only the function generated from the template when it is
instantiated has the type "A const&". But such a function is a non-template.
Still, such a function is not a "non-template function", because of the
special meaning of "non-template function" in the Standard, kept over from
the ARM.

In the above, there wasn't even any function generated. There was just the
function template with parameter type "const T&". Where do you see the copy
constructor?

"The above template isn't even a constructor until its [sic] instantiated."
-> Not true. It is a template constructor / constructor template / templated
constructor / whatever you want to call it. When it is instantiated, the
result is a non-template. It's a function. For an example where it matters:
The spec says "A declaration of a constructor for a class X is ill-formed if
its first parameter is of type (optionally cv-qualified) X and either there
are no other parameters or else all other parameters have default
arguments.", and consequently, comeau/gcc/clang reject the following code

struct A {
template<typename T>
A(A); // ill-formed constructor
};

No instantiation what-so-ever is needed.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to call an inherited, template class constructor from initializerlist of an inheriting, non-template class constructor l.s.rockfan@web.de C++ 4 11-15-2008 01:22 PM
how to call an inherited, template class constructor from initializerlist of an inheriting, non-template class constructor l.s.rockfan@web.de C++ 2 11-14-2008 10:04 PM
A constructor calling another constructor (default constructor)? Generic Usenet Account C++ 10 11-28-2007 04:12 AM
Calling base class constructor from derived class Copy constructor ali C++ 4 03-05-2007 09:15 AM
Copy constructor hides default constructor Aire C++ 3 01-25-2004 05:47 PM



Advertisments