Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Template conversion and default copy constructor

3 views
Skip to first unread message

Stephan Tolksdorf

unread,
Jul 20, 2006, 6:27:09 PM7/20/06
to
Hi

All the compilers I tested produced from the following code executables
that printed "2". Shouldn't the implicitly defined copy constructor be
called?

--
#include <iostream>

class Test{
public:
Test() : data(0) {}
template <typename T> Test(T& test) : data(2) { }
int data;
};

int main(int argc, char* argv[]) {
Test t1;
t1.data = 3;
Test t2(t1);
std::cout << t2.data;

}
--

Regards,
Stephan

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Victor Bazarov

unread,
Jul 21, 2006, 10:44:21 AM7/21/06
to
Stephan Tolksdorf wrote:
> > All the compilers I tested produced from the following code
> > executables that printed "2". Shouldn't the implicitly defined copy
> > constructor be called?
> >
> > --
> > #include <iostream>
> >
> > class Test{
> > public:
> > Test() : data(0) {}
> > template <typename T> Test(T& test) : data(2) { }
> > int data;
> > };
> >
> > int main(int argc, char* argv[]) {
> > Test t1;
> > t1.data = 3;
> > Test t2(t1);
> > std::cout << t2.data;
> >
> > }

No. A templated constructor never replaces the [compiler-defined]
copy constructor.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

Frederick Gotham

unread,
Jul 21, 2006, 10:42:18 AM7/21/06
to
Stephan Tolksdorf posted:

> > Shouldn't the implicitly defined copy constructor be
> > called?


Nice catch.

Indeed, vanilla functions take precedence over template functions.

Does the Standard say that template functions can replace the "miranda"
member functions? I don't think it clarifies that point.


--
Frederick Gotham

Earl Purple

unread,
Jul 21, 2006, 10:40:03 AM7/21/06
to

Stephan Tolksdorf wrote:
> > Hi
> >
> > All the compilers I tested produced from the following code executables
> > that printed "2". Shouldn't the implicitly defined copy constructor be
> > called?
> >
> > --
> > #include <iostream>
> >
> > class Test{
> > public:
> > Test() : data(0) {}
> > template <typename T> Test(T& test) : data(2) { }
> > int data;
> > };
> >
> > int main(int argc, char* argv[]) {
> > Test t1;
> > t1.data = 3;
> > Test t2(t1);
> > std::cout << t2.data;
> >
> > }
> > --

No, the default copy-constructor is a closer match (being an exact
match) than the templated one and is called instead.

Matthias Hofmann

unread,
Jul 21, 2006, 11:20:29 PM7/21/06
to
"Stephan Tolksdorf" <ando...@gmx.de> schrieb im Newsbeitrag
news:e9omrk$3ku$1...@news01.versatel.de...

> > Hi
> >
> > All the compilers I tested produced from the following code executables
> > that printed "2". Shouldn't the implicitly defined copy constructor be
> > called?

<Skipping code>

You are right, the output should be "3", which is the case with Microsoft
Visual C++ 7.0. Which compilers have you tested?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

kanze

unread,
Jul 21, 2006, 11:24:22 PM7/21/06
to
Stephan Tolksdorf wrote:

> > All the compilers I tested produced from the following code
> > executables that printed "2". Shouldn't the implicitly defined
> > copy constructor be called?

> > --
> > #include <iostream>

> > class Test{
> > public:
> > Test() : data(0) {}
> > template <typename T> Test(T& test) : data(2) { }
> > int data;
> > };

> > int main(int argc, char* argv[]) {
> > Test t1;
> > t1.data = 3;
> > Test t2(t1);
> > std::cout << t2.data;
> > }

That's a good question. I don't see any context where the copy
constructor is implicitly called for. In "Test t2(t1);" (or for
that matter, in "Test t2 = t1;", since t1 and t2 have the same
type), the standard says simply that "The applicable
constructors are enumerated, and the best one is chosen through
oeverload resolution." The implicit copy constructor is there,
of course, and is considered in overload resolution, so it is a
question of which is the better match. (If they are otherwise
equal, preference goes to the non-template version.) In this
case, I think that binding the non-const object to a non-const
reference wins out, by the rule in §13.3.3.2/2, point 5: "S1 and
S2 are reference bindings, and the types to which the reference
refers are the same type except for top-level cv-qualifiers, and
the type to which the reference initialized by S2 refers is more
cv-qualifed than the type to which the reference initialized by
S1 refers." (There is, presumably, an "S1 is a better
conversion sequence than S2" somewhere before the list of
points, but I can't find it.) Basically, this is the same rule
which makes the compiler prefer non-const functions to const, or
in general a non-const reference to a const reference, when the
call would be legal for both.

If you change the parameter of the template constructor to T
const&, the compiler generated default should be called.
Similarly, if you explicitly provide a copy constructor which
takes a non-const Test&, it should be provided. But in the case
at hand, t1 is considered a better match for T& (where T is
instantiated as Test) than for the Test const& parameter of the
implicitly generated constructor.

--
James Kanze GABI Software
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

Frederick Gotham

unread,
Jul 22, 2006, 6:06:57 AM7/22/06
to
Victor Bazarov posted:

> Stephan Tolksdorf wrote:
>> > All the compilers I tested produced from the following code
>> > executables that printed "2". Shouldn't the implicitly defined copy
>> > constructor be called?

> No. A templated constructor never replaces the [compiler-defined]
> copy constructor.


You answer "No", yet state that the miranda copy constructor should be called
rather than the template one...

Every compiler he/she tried it on invokes the template function rather than
the miranda function.


--

Frederick Gotham

Jiang

unread,
Jul 22, 2006, 6:03:26 AM7/22/06
to
> All the compilers I tested produced from the following code executables
> that printed "2". Shouldn't the implicitly defined copy constructor be
> called?
>


Yes, template constructor is constructor, but it will never be used
as copy constructor, since we need consistent copy semantics in every
TUs.

I tested your example using gcc, cl, como and icl, only icl gives
correct/expected result.

My icl shows me that:

$ cat test.cpp

#include <iostream>

class Test{
public:
Test() : data(0) {}
template <typename T> Test(T& test) : data(2) { }
int data;

};

int main(int argc, char* argv[]) {
Test t1;
t1.data = 3;
Test t2(t1);
std::cout << t2.data;

}

$ icl test.cpp
Intel(R) C++ Compiler for 32-bit applications, Version 9.0 Build
20050430Z
Copyright (C) 1985-2005 Intel Corporation. All rights reserved.

test.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.

-out:test.exe
test.obj

$ ./test
3


#BTW, if you change the template constructor as (add const specifier):

// ...
template <typename T> Test(T const & test) : data(2) { }

then all compilers will give you correct answer "3".

Frederick Gotham

unread,
Jul 22, 2006, 6:06:37 AM7/22/06
to
Earl Purple posted:


> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.


But the OP said that every compiler he/she tried it on did the exact
opposite. . .


--

Frederick Gotham

Jiang

unread,
Jul 22, 2006, 1:23:20 PM7/22/06
to

Earl Purple wrote:
> Stephan Tolksdorf wrote:
> > > Hi
> > >
> > > All the compilers I tested produced from the following code executables
> > > that printed "2". Shouldn't the implicitly defined copy constructor be
> > > called?
> > >
> > > --
> > > #include <iostream>
> > >
> > > class Test{
> > > public:
> > > Test() : data(0) {}
> > > template <typename T> Test(T& test) : data(2) { }
> > > int data;
> > > };
> > >
> > > int main(int argc, char* argv[]) {
> > > Test t1;
> > > t1.data = 3;
> > > Test t2(t1);
> > > std::cout << t2.data;
> > >
> > > }
> > > --
>
> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.
>

Not true.

In 12.8.p3, the standard says that a member function template
is never instantiated to perform the copy of a class object to an
object of its class type.

So overload resolution is totally irrelative here in my mind.

Matthias Hofmann

unread,
Jul 22, 2006, 2:13:46 PM7/22/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1153480710.5...@75g2000cwc.googlegroups.com...

> The implicit copy constructor is there,
> of course, and is considered in overload resolution, so it is a
> question of which is the better match.

What about this:

12.8/3: "A member function template is never instantiated to perform the


copy of a class object to an object of its class type."

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 22, 2006, 2:14:07 PM7/22/06
to
> Yes, template constructor is constructor, but it will never be used
> as copy constructor, since we need consistent copy semantics in every
> TUs.

This is the first time that someone seems to be able to tell the reason for
that rule. However, I do not quite undertsand it: How would the use of a
template constructor affect the consistency of copy semantics throughout
several translation units?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Dennett

unread,
Jul 22, 2006, 2:11:05 PM7/22/06
to
Victor Bazarov wrote:
> Stephan Tolksdorf wrote:
>>> All the compilers I tested produced from the following code
>>> executables that printed "2". Shouldn't the implicitly defined copy
>>> constructor be called?
>>>
>>> --
>>> #include <iostream>
>>>
>>> class Test{
>>> public:
>>> Test() : data(0) {}
>>> template <typename T> Test(T& test) : data(2) { }
>>> int data;
>>> };
>>>
>>> int main(int argc, char* argv[]) {
>>> Test t1;
>>> t1.data = 3;
>>> Test t2(t1);
>>> std::cout << t2.data;
>>>
>>> }
>
> No. A templated constructor never replaces the [compiler-defined]
> copy constructor.

But as in the example code, it might be a better match that
the (compiler-declared/defined) copy constructor.

-- James

Stephan Tolksdorf

unread,
Jul 22, 2006, 2:14:29 PM7/22/06
to
Earl Purple wrote:
> Stephan Tolksdorf wrote:
>>> Hi
>>>
>>> All the compilers I tested produced from the following code executables
>>> that printed "2". Shouldn't the implicitly defined copy constructor be
>>> called?
>>>
>>> --
>>> #include <iostream>
>>>
>>> class Test{
>>> public:
>>> Test() : data(0) {}
>>> template <typename T> Test(T& test) : data(2) { }
>>> int data;
>>> };
>>>
>>> int main(int argc, char* argv[]) {
>>> Test t1;
>>> t1.data = 3;
>>> Test t2(t1);
>>> std::cout << t2.data;
>>>
>>> }
>>> --
>
> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.

That was my initial thought too, but is it really an exact match? The
implicitly-declared copy constructor uses a *const* reference.

If there were two copy constructors, one taking a const reference and
one taking a non-const reference, Test(t1) would be resolved to a call
to the non-const reference constructor. Footnote 106) in 12.8.2 of the
standard says: "Template constructors participate in overload resolution
with other constructors, including copy constructors, and a template
constructor may be used to copy an object if it provides a better match
than the other constructors."

So, isn't the template constructor the better match and hence should be
called?

Stephan

Matthias Hofmann

unread,
Jul 22, 2006, 2:12:43 PM7/22/06
to
> Nice catch.
>
> Indeed, vanilla functions take precedence over template functions.
>
> Does the Standard say that template functions can replace the "miranda"
> member functions? I don't think it clarifies that point.

At least for the case of copy constructors, it does:

12.8/3: "A member function template is never instantiated to perform the
copy of a class object to an object of its class type."

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Gene Bushuyev

unread,
Jul 22, 2006, 2:12:14 PM7/22/06
to
"Stephan Tolksdorf" <ando...@gmx.de> wrote in message
news:e9omrk$3ku$1...@news01.versatel.de...

> Hi
>
> All the compilers I tested produced from the following code executables
> that printed "2". Shouldn't the implicitly defined copy constructor be
> called?
>
> --
> #include <iostream>
>
> class Test{
> public:
> Test() : data(0) {}
> template <typename T> Test(T& test) : data(2) { }
> int data;
> };
>
> int main(int argc, char* argv[]) {
> Test t1;
> t1.data = 3;
> Test t2(t1);
> std::cout << t2.data;
>
> }
> --


You are absolutely right, the implicitly generated copy constructor should be
called. So all the compilers you tested that print 2 have bugs. I also got "2"
from gcc 3.3.1 and vc8, but amazingly Borland bcc32 5.82 got it right printing
"3"
Good catch.
--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George Orwell

Seungbeom Kim

unread,
Jul 22, 2006, 2:17:34 PM7/22/06
to
Earl Purple wrote:
> Stephan Tolksdorf wrote:
>>> Hi
>>>
>>> All the compilers I tested produced from the following code executables
>>> that printed "2". Shouldn't the implicitly defined copy constructor be
>>> called?
>>>
>>> --
>>> #include <iostream>
>>>
>>> class Test{
>>> public:
>>> Test() : data(0) {}
>>> template <typename T> Test(T& test) : data(2) { }
>>> int data;
>>> };
>>>
>>> int main(int argc, char* argv[]) {
>>> Test t1;
>>> t1.data = 3;
>>> Test t2(t1);
>>> std::cout << t2.data;
>>>
>>> }
>>> --
>
> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.

Then why does t2.data get 2, which must be from the template constructor?
If the default copy constructor were called, it should get 3.

And this is precisely the point that the OP seems to have made,
but strangely people are saying "No" and then repeating the OP's point..
What am I missing here?

--
Seungbeom Kim

Matthias Hofmann

unread,
Jul 22, 2006, 2:13:25 PM7/22/06
to
> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.

The reason that the implicitly defined copy constructor must be called is
the following:

12.8/3: "A member function template is never instantiated to perform the
copy of a class object to an object of its class type."

Matthias Hofmann


Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Kai-Uwe Bux

unread,
Jul 22, 2006, 2:28:30 PM7/22/06
to
Jiang wrote:

12.8/3 refers to constructors with signature

X ( X )

not to copy constructors, whose signature must be

X ( X [const] [volatile] & )


Thus, 12.8/3 does not apply here.

Best

Kai-Uwe Bux

James Kanze

unread,
Jul 22, 2006, 2:31:12 PM7/22/06
to
Victor Bazarov wrote:
> Stephan Tolksdorf wrote:
>>> All the compilers I tested produced from the following code
>>> executables that printed "2". Shouldn't the implicitly defined copy
>>> constructor be called?

>>> --
>>> #include <iostream>

>>> class Test{
>>> public:
>>> Test() : data(0) {}
>>> template <typename T> Test(T& test) : data(2) { }
>>> int data;
>>> };

>>> int main(int argc, char* argv[]) {
>>> Test t1;
>>> t1.data = 3;
>>> Test t2(t1);
>>> std::cout << t2.data;
>>> }

> No. A templated constructor never replaces the [compiler-defined]
> copy constructor.

I'm not sure what you mean by "replaces" here. A templated constructor
never inhibits the generation of the compiler default. But it is still
considered in overload resolution, in cases where the copy constructor
is not required. In the above code, there is no place where the
standard specifies that the copy constructor should be used. In all of
the constructors in this code, overload resolution is used to decide
which constructor to call. And since the instantiated template function
is a better match than the default copy constructor, it gets called.

--
James Kanze kanze...@neuf.fr


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

James Kanze

unread,
Jul 22, 2006, 2:31:56 PM7/22/06
to
Frederick Gotham wrote:
> Stephan Tolksdorf posted:

>>> Shouldn't the implicitly defined copy constructor be
>>> called?

> Nice catch.

> Indeed, vanilla functions take precedence over template functions.

They did, if I recall correctly, in some early implementations.
According to the standard, however, non-template over template is only a
tie-breaker, used in cases where the two functions were otherwise equal.

> Does the Standard say that template functions can replace the
> "miranda" member functions? I don't think it clarifies that point.

A templated constructor never inhibates the generation of the default
copy constructor, and a templated constructor is never used as a copy
constructor. Since there were no cases where the standard called for a
copy constructor in the original code, however, this is irrelevant.
Function overload resolution occurs, and the constructor
Test::Test(Test&) (instantiation of the template) is a better match than
Test::Test(Test const&) (the compiler generated default copy
constructor).

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 22, 2006, 3:31:23 PM7/22/06
to
Earl Purple wrote:
> Stephan Tolksdorf wrote:

>>> All the compilers I tested produced from the following code executables
>>> that printed "2". Shouldn't the implicitly defined copy constructor be
>>> called?

>>> --
>>> #include <iostream>

>>> class Test{
>>> public:
>>> Test() : data(0) {}
>>> template <typename T> Test(T& test) : data(2) { }
>>> int data;
>>> };

>>> int main(int argc, char* argv[]) {
>>> Test t1;
>>> t1.data = 3;
>>> Test t2(t1);
>>> std::cout << t2.data;
>>> }
>>> --

> No, the default copy-constructor is a closer match (being an exact
> match) than the templated one and is called instead.

I think you mistyped here. Didn't you mean the reverse? (The basic way
the sentence is formulated suggests to me that you actually did
understand what was going on, and just inversed the two terms when
typing.)

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 22, 2006, 3:31:44 PM7/22/06
to
Jiang wrote:
>> All the compilers I tested produced from the following code executables
>> that printed "2". Shouldn't the implicitly defined copy constructor be
>> called?

> Yes, template constructor is constructor, but it will never be used as
> copy constructor, since we need consistent copy semantics in every
> TUs.

Correct, but the key to understanding what is occuring here is to
realize that there is no "copying", in the sense of the standard. So
normal function overloading takes place, and the instantiation of the
template is a better match. (But I'll admit that I had to reread the
relevant passages in the standard several times myself before I came to
this conclusion. Overload resolution is all to often a guessing game,
in which you try to guess what the compiler will do this time.)

> $ cat test.cpp

Except that the correct answer here is 2.

> #BTW, if you change the template constructor as (add const specifier):
> // ...
> template <typename T> Test(T const & test) : data(2) { }

> then all compilers will give you correct answer "3".

One of the subtilities of operator overloading and template type
deduction. Template type deduction generates the constructor
Test::Test(Test&) in the original code, which is a better match than the
default Test::Test(Test const&). With the above modification, it
generates Test::Test(Test const&), which is an equal match with the
compiler generated default (which is always present), and in case of an
otherwise equal match, the non template compiler generated default gets
the nod.

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 23, 2006, 8:16:29 AM7/23/06
to
> > In 12.8.p3, the standard says that a member function template
> > is never instantiated to perform the copy of a class object to an
> > object of its class type.
> >
> > So overload resolution is totally irrelative here in my mind.
>
> 12.8/3 refers to constructors with signature
>
> X ( X )

There is no such thing as a constructor with that signature. 12.8/3 says
that they are ill-formed.

> not to copy constructors, whose signature must be
>
> X ( X [const] [volatile] & )

Please read 12.8/3 again. It also says that a member function template is


never instantiated to perform the copy of a class object to an object of its

class type, thus refering to copy constructors.

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 23, 2006, 8:13:04 AM7/23/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1153480710.5...@75g2000cwc.googlegroups.com...

>> The implicit copy constructor is there, of course, and is
>> considered in overload resolution, so it is a question of
>> which is the better match.

> What about this:

> 12.8/3: "A member function template is never instantiated to
> perform the copy of a class object to an object of its class
> type."

Where's the copy? The whole point is that in the context given,
the compiler doesn't call the copy constructor; it makes a list
of available constructors, and applies overload resolution to
choose one.

Also, the quote is taken out of context. It is, IMHO, poorly
worded, but the preceding sentence and the example make it clear
that it is talking about constructors of the form Test(T),
(where T is the template parameter). The immediately preceding
sentence says that a constructor of the form Test(Test) is
illegal; the sentence you quote says that the compiler will
never instantiate a template to create one.

--
James Kanze kanze...@neuf.fr


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

Matthias Hofmann

unread,
Jul 23, 2006, 8:18:18 AM7/23/06
to
> Footnote 106) in 12.8.2 of the
> standard says: "Template constructors participate in overload resolution
> with other constructors, including copy constructors, and a template
> constructor may be used to copy an object if it provides a better match
> than the other constructors."

A template constructor need not be a copy constructor, and 12.8/3 says that
a member function template is never instantiated to perform the copy of a


class object to an object of its class type.

By the way, footnote 106 also says that a template constructor is never a
copy constructor.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

Matthias Hofmann

unread,
Jul 23, 2006, 8:17:38 AM7/23/06
to
> > No, the default copy-constructor is a closer match (being an exact
> > match) than the templated one and is called instead.
>
> Then why does t2.data get 2, which must be from the template constructor?
> If the default copy constructor were called, it should get 3.

Obviously it's a compiler bug.

> And this is precisely the point that the OP seems to have made,
> but strangely people are saying "No" and then repeating the OP's point..
> What am I missing here?

This confused me, too. Apparently they meant "Yes" when they said "No".

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Howard Hinnant

unread,
Jul 23, 2006, 8:13:48 AM7/23/06
to
In article <44c1ffcf$0$22010$9b4e...@newsread2.arcor-online.net>,
"Matthias Hofmann" <hof...@anvil-soft.com> wrote:

> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1153480710.5...@75g2000cwc.googlegroups.com...
>
> > The implicit copy constructor is there,
> > of course, and is considered in overload resolution, so it is a
> > question of which is the better match.
>
> What about this:
>
> 12.8/3: "A member function template is never instantiated to perform the
> copy of a class object to an object of its class type."

12.8p3 is specifically referring to:

struct S {
template<typename T> S(T);
};

not:

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

Admittedly that could be clearer. It is somewhat clarified by the
footnote in 12.8p2:

> Because a template constructor is never a copy constructor, the presence of
> such a template does not suppress the implicit declaration of a copy
> constructor. Template constructors participate in overload resolution with

> other constructors, including copy constructors, and a template constructor

> may be used to copy an object if it provides a better match than other
> constructors.

-Howard

Francis Glassborow

unread,
Jul 23, 2006, 8:19:02 AM7/23/06
to
In article <44c1fd6e$0$24896$9b4e...@newsread4.arcor-online.net>,
Matthias Hofmann <hof...@anvil-soft.com> writes

>12.8/3: "A member function template is never instantiated to perform the
>copy of a class object to an object of its class type."
>
Yet footnote 106 concludes with

and a template constructor may be used to copy an object if it provides
a better match than other constructors.

Now it is only a footnote so not normative but it does go to show
considerable confusion in the minds of the authors

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Francis Glassborow

unread,
Jul 23, 2006, 8:19:24 AM7/23/06
to
In article <1153494631....@i3g2000cwc.googlegroups.com>, Jiang
<goo.m...@yahoo.com> writes

>Not true.
>
>In 12.8.p3, the standard says that a member function template
>is never instantiated to perfo

MY copy of the Standard says no such thing. Indeed footnote 106 seems to
say the exact opposite of what you are claiming


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Matthias Hofmann

unread,
Jul 23, 2006, 8:17:00 AM7/23/06
to
> Since there were no cases where the standard called for a
> copy constructor in the original code, however, this is irrelevant.
> Function overload resolution occurs, and the constructor
> Test::Test(Test&) (instantiation of the template) is a better match than
> Test::Test(Test const&) (the compiler generated default copy
> constructor).

Let's quote the relevant part of the original code again:

int main( int argc, char* argv[] )


{
Test t1;
t1.data = 3;
Test t2( t1 );
std::cout << t2.data;
}

Now please explain to me why in the line that says

Test t2( t1 );

there is no copy constructor invoked? It seems to be a very obvious example
of copy constructing an object to me...

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Gene Bushuyev

unread,
Jul 23, 2006, 8:22:57 AM7/23/06
to
"James Kanze" <kanze...@neuf.fr> wrote in message
news:e9t55s$58s$1...@nntp.aioe.org...

> Jiang wrote:
>>> All the compilers I tested produced from the following code executables
>>> that printed "2". Shouldn't the implicitly defined copy constructor be
>>> called?
>
>> Yes, template constructor is constructor, but it will never be used as
>> copy constructor, since we need consistent copy semantics in every
>> TUs.
>
> Correct, but the key to understanding what is occuring here is to
> realize that there is no "copying", in the sense of the standard. So
> normal function overloading takes place, and the instantiation of the
> template is a better match. (But I'll admit that I had to reread the
> relevant passages in the standard several times myself before I came to
> this conclusion. Overload resolution is all to often a guessing game,
> in which you try to guess what the compiler will do this time.)


I must admit, what appeared a very simple question at first, turned out to be
more difficult especially in the light of unfortunate wording of the standard.
So my original reply that was written two days ago is wrong.
Interesting that compilers also disagree, and those who write them are supposed
to be the language experts. It looks like gcc and vc8 got it right after all,
and Borland is wrong this time.
That also indicates that it's a good practice to make all constructors
consistent without "special effects."

--
Gene Bushuyev (www.gbresearch.com)
----------------------------------------------------------------
To see what is in front of one's nose needs a constant struggle ~ George Orwell

Matthias Hofmann

unread,
Jul 23, 2006, 8:28:07 AM7/23/06
to
> You are absolutely right, the implicitly generated copy constructor should
be
> called. So all the compilers you tested that print 2 have bugs. I also got
"2"
> from gcc 3.3.1 and vc8, but amazingly Borland bcc32 5.82 got it right
printing
> "3"
> Good catch.

Visual C++ 8 prints "2"? This is bad news, because Visual C++ 7.0 prints
"3". This is a little off topic, but I recently tried to install boost
1.33.1 and it failed, because it regarded vc7 as obsolete. Maybe those
"boosters" should look twice.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 23, 2006, 8:22:13 AM7/23/06
to
Matthias Hofmann wrote:
>> No, the default copy-constructor is a closer match (being an exact
>> match) than the templated one and is called instead.

> The reason that the implicitly defined copy constructor must
> be called is the following:

> 12.8/3: "A member function template is never instantiated to
> perform the copy of a class object to an object of its class
> type."

But there is no "copy" in the code in question, at least not in
the sense of the standard. The compiler isn't looking for a
copy constructor here; it is looking for the best matching
constructor.

Also, as another poster pointed out, this phrase has been taken
out of context. In context, it is clear that it means that the
compiler would never instantiate a
template< typename T> Test( T ) ;
with T equal Test. Which is not the case here either.

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 23, 2006, 8:21:10 AM7/23/06
to

>>>> --
>>>> #include <iostream>

> Not true.

The passage you cite could be better worded, but it in this
case, we are not "performing a copy", in the sense of the
standard. We are initializing an object with an expression.
The fact that (coïncidentally) the expression happens to have
the same type is irrelevant here.

Curiously enough (and don't ask me why), the fact that the
expression has the same type in:
Test t2 = t1 ;
means that we are NOT performing a copy, whereas if it had a
different type, a copy would be required.

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Jiang

unread,
Jul 23, 2006, 8:36:46 AM7/23/06
to

Kai-Uwe Bux wrote:

> Jiang wrote:
>
> > Not true.
> >
> > In 12.8.p3, the standard says that a member function template
> > is never instantiated to perform the copy of a class object to an
> > object of its class type.
> >
> > So overload resolution is totally irrelative here in my mind.
>
> 12.8/3 refers to constructors with signature
>
> X ( X )
>
> not to copy constructors, whose signature must be
>
> X ( X [const] [volatile] & )
>
>
> Thus, 12.8/3 does not apply here.
>

You are correct, and I apologize for the confusion I've made.
What I said is true but it is irrelative to the OP.

To make it clearer, for class

struct S {
template<typename T> S(T);
};

, the template has nothing to do with the copy constructor
if T is S itself, otherwise the template will be instantiated and
will participate in constructor overload resolution.

Thank you again for the correction.

Jiang

unread,
Jul 23, 2006, 8:36:24 AM7/23/06
to
James Kanze wrote:
> Jiang wrote:
> >> All the compilers I tested produced from the following code executables
> >> that printed "2". Shouldn't the implicitly defined copy constructor be
> >> called?
>
> > Yes, template constructor is constructor, but it will never be used as
> > copy constructor, since we need consistent copy semantics in every
> > TUs.
>
> Correct, but the key to understanding what is occuring here is to
> realize that there is no "copying", in the sense of the standard. So
> normal function overloading takes place, and the instantiation of the
> template is a better match. (But I'll admit that I had to reread the
> relevant passages in the standard several times myself before I came to
> this conclusion. Overload resolution is all to often a guessing game,
> in which you try to guess what the compiler will do this time.)
>

I reread 8.5 and your previous posts and I must say this is
maybe the source of the inconsistent behaviors.

However, even we stay in the above context, for OP's example,
will the compiler generated default copy constructor be
applicable or not? It seems that some compilers just do not
generate the default copy constructor and the template one
is the only choice, or the overload resolution is wrong.

I will prove this later in this post.


Please see my example below.


> > #BTW, if you change the template constructor as (add const specifier):
> > // ...
> > template <typename T> Test(T const & test) : data(2) { }
>
> > then all compilers will give you correct answer "3".
>
> One of the subtilities of operator overloading and template type
> deduction. Template type deduction generates the constructor
> Test::Test(Test&) in the original code, which is a better match than the
> default Test::Test(Test const&). With the above modification, it
> generates Test::Test(Test const&), which is an equal match with the
> compiler generated default (which is always present), and in case of an
> otherwise equal match, the non template compiler generated default gets
> the nod.
>


It is true. However it seems that the above reasoning does not
describe what is happened here exactly.

To prove it, I changed the OP's example to following one.
(I need such change, because I am not sure whether default
copy constructor for built-in types have parameter of "T const &"
or not, I will start a new thread for this issue.)

[example]

$ cat test.cpp
#include <iostream>

class Test{
public:
Test(){}
template <typename T> Test(T& test){
std::cout<< "template non-const param\n";
}
};

int main(int argc, char* argv[])
{
Test t1;

Test t2(t1);
}

$ como --A test.cpp
Comeau C/C++ 4.3.3 (Jan 13 2004 11:29:09) for MS_WINDOWS_x86
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

$ ./aout
template non-const param

[end example]

Here, I removed the member "data", and according to 12.8/p5,
the compiler will generate the default constructor using
the following form (non-const version):

Test::Test(Test &);

I can not understand the output of the program, because:

1. If this copy constructor is really generated by the
compiler, then for sure it will win in the overload
resolution, and the program should log nothing,
instead of the above message.

2. If there is just no such a copy constructor, then
the something must be wrong, because the standard
says a template constructor is never a copy
constructor and the presence of such a template


does not suppress the implicit declaration of a
copy constructor.

Did I miss anything important?

Jiang

unread,
Jul 23, 2006, 8:35:18 AM7/23/06
to
Matthias Hofmann wrote:
> > Yes, template constructor is constructor, but it will never be used
> > as copy constructor, since we need consistent copy semantics in every
> > TUs.
>
> This is the first time that someone seems to be able to tell the reason for
> that rule. However, I do not quite undertsand it: How would the use of a
> template constructor affect the consistency of copy semantics throughout
> several translation units?
>

The problem is, well, if we allow template copy/assignment constructors
here, then the declarations order will dominate the result of object
construction.

For example, it is possible the template is specialized somewhere and
some TUs will use the specialized one instead of the original template
according to the declaration visibility.

I think the main point is, constructors, together with destructor, are
very special compared with other members. That's why the standard
names them "special member functions".

Matthias Hofmann

unread,
Jul 23, 2006, 1:08:59 PM7/23/06
to

"Francis Glassborow" <fra...@robinton.demon.co.uk> schrieb im Newsbeitrag
news:yPPjtsCS...@robinton.demon.co.uk...

> In article <1153494631....@i3g2000cwc.googlegroups.com>, Jiang
> <goo.m...@yahoo.com> writes
> >Not true.
> >
> >In 12.8.p3, the standard says that a member function template
> >is never instantiated to perfo
>
> MY copy of the Standard says no such thing. Indeed footnote 106 seems to
> say the exact opposite of what you are claiming

Well, then we seem to be using different copies of the standard indeed. In
my version, 12.8/3 says that a member function template is never


instantiated to perform the copy of a class object to an object of its class
type.

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 23, 2006, 3:16:12 PM7/23/06
to
"Francis Glassborow" <fra...@robinton.demon.co.uk> schrieb im Newsbeitrag
news:WfDqpzDj...@robinton.demon.co.uk...

> In article <44c1fd6e$0$24896$9b4e...@newsread4.arcor-online.net>,
> Matthias Hofmann <hof...@anvil-soft.com> writes
> >12.8/3: "A member function template is never instantiated to perform the
> >copy of a class object to an object of its class type."
> >
> Yet footnote 106 concludes with
>
> and a template constructor may be used to copy an object if it provides
> a better match than other constructors.
>
> Now it is only a footnote so not normative but it does go to show
> considerable confusion in the minds of the authors

James Kanze has meanwhile succeeded in clarifying the meaning of 12.8/3 for
me. I would be grateful if somebody now could explain to me how footnote 106
is to be interpreted.

Both 12.8/2 and footnote 106 seem to agree that a template constructor is
never a copy constructor. As you have pointed out, footnote 106 also says
that it can be used to copy objects. I remember that there was a very
similar discussion on this newsgroup some time ago, where the term "copying
constructor" was used for those template constructors. Those "copying
constructors" were said to be able to be used for direct initialization, but
not for copy initialization.

You can find that discussion here:
http://groups.google.de/group/comp.lang.c++.moderated/browse_frm/thread/72f2
4e2c0211bb2b/d475a9de3b90c648

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Kai-Uwe Bux

unread,
Jul 23, 2006, 3:25:32 PM7/23/06
to
Matthias Hofmann wrote:

>> > In 12.8.p3, the standard says that a member function template
>> > is never instantiated to perform the copy of a class object to an
>> > object of its class type.
>> >
>> > So overload resolution is totally irrelative here in my mind.
>>
>> 12.8/3 refers to constructors with signature
>>
>> X ( X )
>
> There is no such thing as a constructor with that signature. 12.8/3 says
> that they are ill-formed.

Exactly, that is why 12.8/3 refers to constructors of this signature: to say
they are ill-formed. Also, note that it does so in the topic sentence. That
tells you something about how to interpret the rest of the paragraph.



>> not to copy constructors, whose signature must be
>>
>> X ( X [const] [volatile] & )
>
> Please read 12.8/3 again. It also says that a member function template is
> never instantiated to perform the copy of a class object to an object of
> its class type, thus refering to copy constructors.

In your next reading of 12.8/3, please pay close attention to the example
that follows the explanation:

[12.8/3]
A declaration of a constructor for a class X is ill-formed if its first
parameter is of type (optionally cvqualified) X and either there are no
other parameters or else all other parameters have default arguments. A


member function template is never instantiated to perform the copy of a

class object to an object of its class type. [Example:

struct S {
template<typename T> S(T);
};

S f();

void g() {
S a( f() ); // does not instantiate member template
}

?end example]


I guess it is pretty clear now, what the member template instantiation issue
is about: the would-be-illformed-when-instantiated template is not
instantiated.


Also, your reading that templates (regardless of their signature) are never
used to copy an object is in direct conflict with footnote 106:

106) Because a template constructor is never a copy constructor, the


presence of such a template does not suppress the implicit declaration

of a copy constructor. Template constructors participate in overload
resolution with other constructors, including copy constructors,

and a template constructor may be used to copy an object if it provides a
better match than other constructors.


Best

Kai-Uwe Bux

Matthias Hofmann

unread,
Jul 23, 2006, 3:25:11 PM7/23/06
to
"James Kanze" <kanze...@neuf.fr> schrieb im Newsbeitrag
news:e9u1kk$hu8$1...@nntp.aioe.org...

> Also, as another poster pointed out, this phrase has been taken
> out of context. In context, it is clear that it means that the
> compiler would never instantiate a
> template< typename T> Test( T ) ;
> with T equal Test. Which is not the case here either.

Now that I am reading 12.8/3 again, I understand your point, and I think you
are right. That passage should maybe reworded to something like the
following:

"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
parameters or else all other parameters have default arguments. Such an
ill-formed constructor is never instantiated from a member function
template."

There's probably a better way to express it, but I guess you know what I
mean. It would prevent much confusion.

--


Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 23, 2006, 3:21:04 PM7/23/06
to
"Jiang" <goo.m...@yahoo.com> schrieb im Newsbeitrag
news:1153635019....@i3g2000cwc.googlegroups.com...

> Matthias Hofmann wrote:
> > > Yes, template constructor is constructor, but it will never be used
> > > as copy constructor, since we need consistent copy semantics in every
> > > TUs.
> >
> > This is the first time that someone seems to be able to tell the reason
for
> > that rule. However, I do not quite undertsand it: How would the use of a
> > template constructor affect the consistency of copy semantics throughout
> > several translation units?
> >
>
> The problem is, well, if we allow template copy/assignment constructors
> here, then the declarations order will dominate the result of object
> construction.
>
> For example, it is possible the template is specialized somewhere and
> some TUs will use the specialized one instead of the original template
> according to the declaration visibility.

But footnote 106 (as well as people in this thread) claims that a template
constructor can be used to copy objects. So how is the compiler supposed to
ensure any consistent copy semantics?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 23, 2006, 3:21:47 PM7/23/06
to
"James Kanze" <kanze...@neuf.fr> schrieb im Newsbeitrag
news:e9u1ak$btg$1...@nntp.aioe.org...

> The passage you cite could be better worded, but it in this
> case, we are not "performing a copy", in the sense of the
> standard. We are initializing an object with an expression.
> The fact that (coïncidentally) the expression happens to have
> the same type is irrelevant here.
>
> Curiously enough (and don't ask me why), the fact that the
> expression has the same type in:
> Test t2 = t1 ;
> means that we are NOT performing a copy, whereas if it had a
> different type, a copy would be required.

How did you get to this conclusion? 12.8/1 says that an object is
conceptually copied by a copy constructor. However, the term "conceptually"
seems rather confusing here... As far as I have learned in this thread, an
object can be copied by:

a.) a copy constructor, which is never a template
b.) a template constructor, which is never a copy constructor

Are you saying that 8.5/14 is NOT AT ALL about copy constructors, or rather
that it is NOT ONLY about copy constructors? I guess that the latter is
correct, which would explain why template constructors may be called in the
original post's example.

To me, the meaning of the term "copy" seems rather vague in this thread. For
example, what is the difference between copying an object and initializing
it with another object of the same type? If I understand 12.8/1 correctly,
both should be the same.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 23, 2006, 8:57:06 PM7/23/06
to
Matthias Hofmann wrote:
> "James Kanze" <kanze...@neuf.fr> schrieb im Newsbeitrag
> news:e9u1ak$btg$1...@nntp.aioe.org...

>> The passage you cite could be better worded, but it in this
>> case, we are not "performing a copy", in the sense of the
>> standard. We are initializing an object with an expression.
>> The fact that (coïncidentally) the expression happens to have
>> the same type is irrelevant here.

>> Curiously enough (and don't ask me why), the fact that the
>> expression has the same type in:
>> Test t2 = t1 ;
>> means that we are NOT performing a copy, whereas if it had a
>> different type, a copy would be required.

> How did you get to this conclusion?

Because §8.5/14 (fourth bullet, second sub-bullet) says so
explicitly.

> 12.8/1 says that an object is conceptually copied by a copy
> constructor. However, the term "conceptually" seems rather
> confusing here...

Very.

> As far as I have learned in this thread, an object can be
> copied by:

> a.) a copy constructor, which is never a template
> b.) a template constructor, which is never a copy constructor

> Are you saying that 8.5/14 is NOT AT ALL about copy
> constructors, or rather that it is NOT ONLY about copy
> constructors? I guess that the latter is correct, which would
> explain why template constructors may be called in the
> original post's example.

My interpretation (and I don't think 8.5/14 makes sense
otherwise) is that when the standard speaks about copying, it is
speaking about cases where it explicitly says that an object
will be copied. In other cases, such as in the example code
here, the fact that the initialization expression happens to
have the same type as the target is more or less a coincidence;
from a standards perspective, it is not copying (although the
copy constructor definitly participates in overload resolution).

I agree that this interpretation doesn't really coincide with
what one would think of the word copy in normal English use.
But I guess I've grown so used to the standard using words in
special ways that it doesn't bother me too much.

> To me, the meaning of the term "copy" seems rather vague in
> this thread. For example, what is the difference between
> copying an object and initializing it with another object of
> the same type? If I understand 12.8/1 correctly, both should
> be the same.

I'm not sure that §12.8/1 is that clear about it. It certainly
initialization can be copying, and some initializations
definitly are copying. I don't think you have to (or should)
interpret it to mean that all initialization is copying, or even
all initialization with the same type is copying. The first
part is obvious, I think; the second goes against an intuitive
interpretation of the word copying, but seems to correspond best
to the text in §8.5/14. And §8.5/12, where the term
"copy-initialization" is defined as "The initialization that
occurs in argument passing, function return, throwing an
exception, handling an exception, and brace-enclosed
initializer lists is called <i>copy-initialization</i> and is
equivalent to the form T x = a;" The fact that
copy-initialization is italicized here means that this is the
definition of the term. (Although the standard then later
specifies one particular case where copy-initialization uses
function overload resolution to choose the constructor, rather
than automatically using the copy constructor.)

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Francis Glassborow

unread,
Jul 23, 2006, 8:52:08 PM7/23/06
to
In article <44c375d1$0$22002$9b4e...@newsread2.arcor-online.net>,
Matthias Hofmann <hof...@anvil-soft.com> writes

>> >In 12.8.p3, the standard says that a member function template
>> >is never instantiated to perfo
>>
>> MY copy of the Standard says no such thing. Indeed footnote 106 seems to
>> say the exact opposite of what you are claiming
>
>Well, then we seem to be using different copies of the standard indeed. In
>my version, 12.8/3 says that a member function template is never
>instantiated to perform the copy of a class object to an object of its class
>type.

Read the text carefully and look at the (non-normative example). It
actually is about something quite different and the sentence you quote
needs to be taken in the context of the previous sentence. Yes the
wording is sloppy but ...

Now here is a pretty minimalist test program:

class example {
example(example const &);
public:
template<typename T> example(T &){}
example(){}
};


int main(){
example /* const */ ex;
example test(ex);
}

Note that this compiles until you unquote the const.

It also fails to compile if you remove the const qualification from the
parameter of the private copy constructor.


--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

James Kanze

unread,
Jul 23, 2006, 8:56:45 PM7/23/06
to
Matthias Hofmann wrote:
>> Since there were no cases where the standard called for a
>> copy constructor in the original code, however, this is
>> irrelevant. Function overload resolution occurs, and the
>> constructor Test::Test(Test&) (instantiation of the template)
>> is a better match than Test::Test(Test const&) (the compiler
>> generated default copy constructor).

> Let's quote the relevant part of the original code again:

> int main( int argc, char* argv[] )
> {
> Test t1;
> t1.data = 3;
> Test t2( t1 );
> std::cout << t2.data;
> }

> Now please explain to me why in the line that says

> Test t2( t1 );

> there is no copy constructor invoked?

Because the standard §8.5/14, point 4, sub-point 2 says that
there isn't. It most explicitly says "If the initialization is
direct initialization [...] The applicable constructors are
enumerated, and the best one is chosen through overload
resolution." The compiler does not consider this a copy; it
considers it normal initialization with a list of values.

> It seems to be a very obvious example of copy constructing an
> object to me...

Common sense would say so, I agree. But since when does common
sense have anything to do with interpreting the standard:-).

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Kanze

unread,
Jul 24, 2006, 9:13:46 AM7/24/06
to
Matthias Hofmann wrote:
>>> In 12.8.p3, the standard says that a member function template
>>> is never instantiated to perform the copy of a class object to an
>>> object of its class type.

>>> So overload resolution is totally irrelative here in my mind.
>> 12.8/3 refers to constructors with signature

>> X ( X )

> There is no such thing as a constructor with that signature.
> 12.8/3 says that they are ill-formed.

That's exactly the point.

>> not to copy constructors, whose signature must be

>> X ( X [const] [volatile] & )

> Please read 12.8/3 again. It also says that a member function
> template is never instantiated to perform the copy of a class
> object to an object of its class type, thus refering to copy
> constructors.

Yes, but the context of this statement makes it more or less
clear that what is being referred to here is templates
constructors of the type "template< typename T >Test( T )".
(But I agree that it could be clearer.)

I think the important thing to keep in mind is that the standard
has a very specific meaning when it says "to make a copy" of
something. The fact that an initializer just happens to have
the same type as what is being initialized does not make it a
copy, or the wording in §8.5/14 doesn't make sense.

--
James Kanze kanze...@neuf.fr
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

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

kanze

unread,
Jul 24, 2006, 9:37:57 AM7/24/06
to
Jiang wrote:
> James Kanze wrote:
> > Jiang wrote:
> > >> All the compilers I tested produced from the following
> > >> code executables that printed "2". Shouldn't the
> > >> implicitly defined copy constructor be called?

> > > Yes, template constructor is constructor, but it will
> > > never be used as copy constructor, since we need
> > > consistent copy semantics in every TUs.

> > Correct, but the key to understanding what is occuring here
> > is to realize that there is no "copying", in the sense of
> > the standard. So normal function overloading takes place,
> > and the instantiation of the template is a better match.
> > (But I'll admit that I had to reread the relevant passages
> > in the standard several times myself before I came to this
> > conclusion. Overload resolution is all to often a guessing
> > game, in which you try to guess what the compiler will do
> > this time.)

> I reread 8.5 and your previous posts and I must say this is
> maybe the source of the inconsistent behaviors.

The source of the inconsistent behaviors is probably simply that
even the best compiler writers can't think of everything,
everywhere.

> However, even we stay in the above context, for OP's example,
> will the compiler generated default copy constructor be
> applicable or not? It seems that some compilers just do not
> generate the default copy constructor and the template one is
> the only choice, or the overload resolution is wrong.

I've seen no evidence of this. I suspect that all of the
compilers probably generate the default copy constructor. I
suspect, equally, that most of them get the overload resolution
right when they apply it (but this may not be the case with some
older compilers). I suspect that the difference is whether the
compiler treats the case in question as a "copy" or not.

[...]


> > One of the subtilities of operator overloading and template
> > type deduction. Template type deduction generates the
> > constructor Test::Test(Test&) in the original code, which is
> > a better match than the default Test::Test(Test const&).
> > With the above modification, it generates Test::Test(Test
> > const&), which is an equal match with the compiler generated
> > default (which is always present), and in case of an
> > otherwise equal match, the non template compiler generated
> > default gets the nod.

> It is true. However it seems that the above reasoning does not
> describe what is happened here exactly.

> To prove it, I changed the OP's example to following one. (I
> need such change, because I am not sure whether default copy
> constructor for built-in types have parameter of "T const &"
> or not, I will start a new thread for this issue.)

The signature of the compiler generated copy constructor here
will be Test( Test const& ). But you're right that §12.8/5
could express it clearer. But I don't think that there's any
question about it. The signature will be Test( Test const& )
unless at least one base class or member of class type has a
copy constructor whose signature does not take the const.

Basically, if you consider the two bullets in §12.8/5, there are
no direct or virtual base classes, so all of the direct or
virtual base classes have the required copy constructor, and
there are no members of class type, so all of the members of
class type have the required copy constructor.

Obviously, this would be a lot clearer if the authors' of this
passage had used the more usual form of expression, using
"unless" instead of if, and something along the lines of "there
existes ... which doesn't have...". But in formal logic, if
there are no X, then all X have property Y. For all possible
property Y, of course.

> [example]

> $ cat test.cpp
> #include <iostream>

> class Test{
> public:
> Test(){}
> template <typename T> Test(T& test){
> std::cout<< "template non-const param\n";
> }
> };

> int main(int argc, char* argv[])
> {
> Test t1;
> Test t2(t1);
> }

> $ como --A test.cpp
> Comeau C/C++ 4.3.3 (Jan 13 2004 11:29:09) for MS_WINDOWS_x86
> Copyright 1988-2003 Comeau Computing. All rights reserved.
> MODE:strict errors C++

> $ ./aout
> template non-const param

> [end example]

> Here, I removed the member "data", and according to 12.8/p5,
> the compiler will generate the default constructor using the
> following form (non-const version):

> Test::Test(Test &);

Not at all. Try this simple test:

class Test { } ;

int
main()
{
Test const t1 ;
Test t2( t1 ) ;
}

The only possible constructor the compiler could use here is the
compiler generated copy constructor. And unless its signature
is: Test::Test( Test const& ), the code won't compile. (And I'd
be very surprised if you find a compiler where it doesn't
compile.)

> I can not understand the output of the program, because:

> 1. If this copy constructor is really generated by the
> compiler, then for sure it will win in the overload
> resolution, and the program should log nothing,
> instead of the above message.

> 2. If there is just no such a copy constructor, then
> the something must be wrong, because the standard
> says a template constructor is never a copy
> constructor and the presence of such a template
> does not suppress the implicit declaration of a
> copy constructor.

> Did I miss anything important?

That the signature of the compiler generated copy constructor is
Test( Test const&) here, and that as in the initial case,
overload resolution choses the template.

--
James Kanze GABI Software


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

kanze

unread,
Jul 24, 2006, 9:38:18 AM7/24/06
to
Gene Bushuyev wrote:
> "James Kanze" <kanze...@neuf.fr> wrote in message
> news:e9t55s$58s$1...@nntp.aioe.org...
> > Jiang wrote:
> >>> All the compilers I tested produced from the following
> >>> code executables that printed "2". Shouldn't the
> >>> implicitly defined copy constructor be called?

> >> Yes, template constructor is constructor, but it will never
> >> be used as copy constructor, since we need consistent copy
> >> semantics in every TUs.

> > Correct, but the key to understanding what is occuring here
> > is to realize that there is no "copying", in the sense of
> > the standard. So normal function overloading takes place,
> > and the instantiation of the template is a better match.
> > (But I'll admit that I had to reread the relevant passages
> > in the standard several times myself before I came to this
> > conclusion. Overload resolution is all to often a guessing
> > game, in which you try to guess what the compiler will do
> > this time.)

> I must admit, what appeared a very simple question at first,
> turned out to be more difficult especially in the light of
> unfortunate wording of the standard.

Not for the first time.

> So my original reply that was written two days ago is wrong.
> Interesting that compilers also disagree, and those who write
> them are supposed to be the language experts. It looks like
> gcc and vc8 got it right after all, and Borland is wrong this
> time.

It's also possible that the compiler authors' didn't actually
consider the issues in detail, and that the behavior more or
less fell out from other internal details.

> That also indicates that it's a good practice to make all
> constructors consistent without "special effects."

As a general rule, I would say that you shouldn't overload
functions if it will make a difference which one would be
called. Trying to know exactly which one overload resolution
will pick is often more of a guessing game than anything else.
With the help of very careful reading of the standard, you can
usually figure out which one should be called, but who wants to
do that kind of analysis every time you see a function call.

Constructors are a special case, because you can't give two
constructors different names just because they do different
things. In at least one case, I've added an extra parameter to
the constructor, just to allow explicit differentiation.

--
James Kanze GABI Software
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

kanze

unread,
Jul 24, 2006, 9:39:28 AM7/24/06
to
Matthias Hofmann wrote:
> "James Kanze" <kanze...@neuf.fr> schrieb im Newsbeitrag
> news:e9u1kk$hu8$1...@nntp.aioe.org...

> > Also, as another poster pointed out, this phrase has been taken
> > out of context. In context, it is clear that it means that the
> > compiler would never instantiate a
> > template< typename T> Test( T ) ;
> > with T equal Test. Which is not the case here either.

> Now that I am reading 12.8/3 again, I understand your point,
> and I think you are right. That passage should maybe reworded
> to something like the following:

> "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 parameters or else all other parameters
> have default arguments. Such an ill-formed constructor is
> never instantiated from a member function template."

> There's probably a better way to express it, but I guess you
> know what I mean. It would prevent much confusion.

Agreed. I think the first paragraph in §12.8 also needs some
work. What on earth does "conceptually [...] implemented by a
copy constructor" mean, for example. And when they say that "a
class object can be copied [...] by initialization", does it
mean any initialization, or just copy-initialization, or...

Section 8.5 goes into rather extreme detail as to how a compiler
should treat initialization; because of its detail, I rather
think it must have precedence over such vague statements as
those which have been quoted from §12.8. But the statements in
§12.8 should certainly be formulated in a manner which doesn't
give rise to expectations of something different.

Also, although I think that §8.5 is fairly clear in this case,
there are other cases where I'm less sure. Generally speaking,
are there cases where the compiler will always call the copy
constructor, without applying overload resolution. Consider,
for example, the third sub-bullet of the second bullet of
§8.5/14, particularly the sentence: "The result of the call
(which is the temporary for the constructor case) is then used
to direct-initialize, ACCORDING TO THE RULES ABOVE." The rules
above imply overload resolution. So given:

class Test
{
private:
Test( Test& ) ;
public:
Test( int ) {}
template< typename T >
Test( T const& ) { std::cout << "template" << std::endl ; }
} ;

int
main()
{
Test t1 = 5 ;
}

Is this code legal or not? If the compiler applies overload
resolution to the copy, it will choose the template constructor
(since the temporary cannot be bound to the non-const reference
of the copy constructor). g++ thinks it's legal, Sun CC no.
But if it's legal (and a strict interpretation of §8.5/14 would
seem to say that it is), then I'm really lost as to the meaning
of the first paragraph of §12.8. It's also rather
disconcerting; I'm used to the fact that a copy constructor can
be elided, and that any side effects in it may not take place,
but in this case, it is a non-copy constructor which is being
elided.

--
James Kanze GABI Software

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

Matthias Hofmann

unread,
Jul 24, 2006, 9:13:27 PM7/24/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1153732876.0...@75g2000cwc.googlegroups.com...

> > As a general rule, I would say that you shouldn't overload
> > functions if it will make a difference which one would be
> > called.

Why would you overload functions if it does not make a difference which one
will be called?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 24, 2006, 9:12:57 PM7/24/06
to
> > Also, although I think that §8.5 is fairly clear in this case,
> > there are other cases where I'm less sure. Generally speaking,
> > are there cases where the compiler will always call the copy
> > constructor, without applying overload resolution. Consider,
> > for example, the third sub-bullet of the second bullet of
> > §8.5/14, particularly the sentence: "The result of the call
> > (which is the temporary for the constructor case) is then used
> > to direct-initialize, ACCORDING TO THE RULES ABOVE." The rules
> > above imply overload resolution. So given:
> >
> > class Test
> > {
> > private:
> > Test( Test& ) ;
> > public:
> > Test( int ) {}
> > template< typename T >
> > Test( T const& ) { std::cout << "template" << std::endl ; }
> > } ;
> >
> > int
> > main()
> > {
> > Test t1 = 5 ;
> > }
> >
> > Is this code legal or not? If the compiler applies overload
> > resolution to the copy, it will choose the template constructor
> > (since the temporary cannot be bound to the non-const reference
> > of the copy constructor). g++ thinks it's legal, Sun CC no.

Good question. I would say that the code is legal, at least I cannot find
any text in 8.5/14 that says otherwise.

> > But if it's legal (and a strict interpretation of §8.5/14 would
> > seem to say that it is), then I'm really lost as to the meaning
> > of the first paragraph of §12.8. It's also rather
> > disconcerting; I'm used to the fact that a copy constructor can
> > be elided, and that any side effects in it may not take place,
> > but in this case, it is a non-copy constructor which is being
> > elided.

The standard only says that "the copying can be elided". Apparently,
template constructors can be used for the direct-initialization part of
copy-initialization, or be elided.

I am confused about the meaning of 12.8/1 myself, but not more than I was
before I read your example.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 24, 2006, 9:18:13 PM7/24/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1153732345.6...@h48g2000cwc.googlegroups.com...

>> > > However, even we stay in the above context, for OP's example,
>> > > will the compiler generated default copy constructor be
>> > > applicable or not? It seems that some compilers just do not
>> > > generate the default copy constructor and the template one is
>> > > the only choice, or the overload resolution is wrong.
> >
> > I've seen no evidence of this. I suspect that all of the
> > compilers probably generate the default copy constructor. I
> > suspect, equally, that most of them get the overload resolution
> > right when they apply it (but this may not be the case with some
> > older compilers). I suspect that the difference is whether the
> > compiler treats the case in question as a "copy" or not.

I think this thread has shown that objects can not only be copied by the
copy constructor. Maybe the term "conceptually" in 12.8/1 means "copy
constructors or template constructors behaving like copy constructors".

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 24, 2006, 9:51:27 PM7/24/06
to
> >> Curiously enough (and don't ask me why), the fact that the
> >> expression has the same type in:
> >> Test t2 = t1 ;
> >> means that we are NOT performing a copy, whereas if it had a
> >> different type, a copy would be required.
>
> > How did you get to this conclusion?
>
> Because §8.5/14 (fourth bullet, second sub-bullet) says so
> explicitly.

I cannot find any part in the text that is so explicit. The second
sub-bullet neither mentions the copy constructor, nor does it talk about an
object being copied, which is actually just your argument. But the text in
the sub-bullet that follows, which is the one that handles
copy-initialization for different source and target types, does not require
a copy either. The only term that comes close to it is a "temporary". Are
temporary objects copies by definition?

> My interpretation (and I don't think 8.5/14 makes sense
> otherwise) is that when the standard speaks about copying, it is
> speaking about cases where it explicitly says that an object
> will be copied. In other cases, such as in the example code
> here, the fact that the initialization expression happens to
> have the same type as the target is more or less a coincidence;
> from a standards perspective, it is not copying (although the
> copy constructor definitly participates in overload resolution).

That makes sense, although it is not intuitive.

> I agree that this interpretation doesn't really coincide with
> what one would think of the word copy in normal English use.
> But I guess I've grown so used to the standard using words in
> special ways that it doesn't bother me too much.

Direct-initialization is always direct-initialization, but
copy-initialization is only sometimes copy-initialization, because sometimes
it is also direct-initialization. That's the standard the way I know it...
;-)

>
> > To me, the meaning of the term "copy" seems rather vague in
> > this thread. For example, what is the difference between
> > copying an object and initializing it with another object of
> > the same type? If I understand 12.8/1 correctly, both should
> > be the same.
>
> I'm not sure that §12.8/1 is that clear about it. It certainly
> initialization can be copying, and some initializations
> definitly are copying. I don't think you have to (or should)
> interpret it to mean that all initialization is copying, or even
> all initialization with the same type is copying.

You mean that initialization with the same type is only sometimes copying?
So when is it, and when is it not? And what do you mean when you say
"copying", copying in the sense of the standard, or copying in the common
English sense of the word?

> The first
> part is obvious, I think; the second goes against an intuitive
> interpretation of the word copying, but seems to correspond best
> to the text in §8.5/14. And §8.5/12, where the term
> "copy-initialization" is defined as "The initialization that
> occurs in argument passing, function return, throwing an
> exception, handling an exception, and brace-enclosed
> initializer lists is called <i>copy-initialization</i> and is
> equivalent to the form T x = a;" The fact that
> copy-initialization is italicized here means that this is the
> definition of the term. (Although the standard then later
> specifies one particular case where copy-initialization uses
> function overload resolution to choose the constructor, rather
> than automatically using the copy constructor.)

12.8/1 simply confuses me. It says that an object can be copied by
initialization, but you say that not all initialization, even with the same
type, is copying.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 24, 2006, 9:50:44 PM7/24/06
to
> >> not to copy constructors, whose signature must be
> >>
> >> X ( X [const] [volatile] & )
> >
> > Please read 12.8/3 again. It also says that a member function template
is
> > never instantiated to perform the copy of a class object to an object of
> > its class type, thus refering to copy constructors.
>
> In your next reading of 12.8/3, please pay close attention to the example
> that follows the explanation:
>
> [12.8/3]
> A declaration of a constructor for a class X is ill-formed if its first
> parameter is of type (optionally cvqualified) X and either there are no
> other parameters or else all other parameters have default arguments. A
> member function template is never instantiated to perform the copy of a
> class object to an object of its class type. [Example:
>
> struct S {
> template<typename T> S(T);
> };
>
> S f();
>
> void g() {
> S a( f() ); // does not instantiate member template
> }
>
> ?end example]
>
>
> I guess it is pretty clear now, what the member template instantiation
issue
> is about: the would-be-illformed-when-instantiated template is not
> instantiated.

I think you are right and I was wrong. I read the second sentence of 12.8/3
out of context, but now I am convinced that it only refers to the ill-formed
constructor.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

Matthias Hofmann

unread,
Jul 24, 2006, 9:51:06 PM7/24/06
to
"Francis Glassborow" <fra...@robinton.demon.co.uk> schrieb im Newsbeitrag
news:HcSe5fEm...@robinton.demon.co.uk...

> In article <44c375d1$0$22002$9b4e...@newsread2.arcor-online.net>,
> Matthias Hofmann <hof...@anvil-soft.com> writes
> >> >In 12.8.p3, the standard says that a member function template
> >> >is never instantiated to perfo
> >>
> >> MY copy of the Standard says no such thing. Indeed footnote 106 seems
to
> >> say the exact opposite of what you are claiming
> >
> >Well, then we seem to be using different copies of the standard indeed.
In
> >my version, 12.8/3 says that a member function template is never
> >instantiated to perform the copy of a class object to an object of its
class
> >type.
>
> Read the text carefully and look at the (non-normative example). It
> actually is about something quite different and the sentence you quote
> needs to be taken in the context of the previous sentence. Yes the
> wording is sloppy but ...

You are right, my quoting the sentence out of context was a mistake. The
wording is indeed sloppy, but the example makes it rather clear.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

James Dennett

unread,
Jul 25, 2006, 6:42:00 AM7/25/06
to
Matthias Hofmann wrote:
> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
> news:1153732876.0...@75g2000cwc.googlegroups.com...
>
>>> As a general rule, I would say that you shouldn't overload
>>> functions if it will make a difference which one would be
>>> called.
>
> Why would you overload functions if it does not make a difference which one
> will be called?

(1) To allow calling with a wider range of argument types
(2) For efficiency

On the other hand, why would you design an interface such
that a user has to consider the result of overload resolution
in order to know which operation will be performed? If they
operations are that different, they should have different
names.

-- James

Jiang

unread,
Jul 25, 2006, 7:23:24 AM7/25/06
to
>
> The source of the inconsistent behaviors is probably simply that
> even the best compiler writers can't think of everything,
> everywhere.
>

Agree.

And things will become worse if the standard can not help them
using better wording. :-)

Really a tough job, for both compiler writers and standard
writers. :-)

> The signature of the compiler generated copy constructor here
> will be Test( Test const& ). But you're right that §12.8/5
> could express it clearer. But I don't think that there's any
> question about it. The signature will be Test( Test const& )
> unless at least one base class or member of class type has a
> copy constructor whose signature does not take the const.
>
> Basically, if you consider the two bullets in §12.8/5, there are
> no direct or virtual base classes, so all of the direct or
> virtual base classes have the required copy constructor, and
> there are no members of class type, so all of the members of
> class type have the required copy constructor.
>


As other rules in standard, the wording is like this:

The implicitly-declared copy constructor ... will be

X::X(const X&)

if
condition 1 here, and
condition 2 here

Otherwise, it will have form

X::X(X &)

Here the word "otherwise" is indeed problematic, since the
class Test does not have any base classes and members,
then the two specified conditions can not be satisfied.
Thus, the default copy constructor should be the non-const
form. That was what I read it.

Now I would like to say this is unspecified behavior.

BTW, I started a new thread for this issue, but unfortunately
so far there is no response.


cl and icl accepted above code, but it wont compile using
como and gcc.

$ como --A test.cpp
Comeau C/C++ 4.3.3 (Jan 13 2004 11:29:09) for MS_WINDOWS_x86
Copyright 1988-2003 Comeau Computing. All rights reserved.
MODE:strict errors C++

"test.cpp", line 9: error: const variable "t1" requires an initializer
--
class "Test" has no explicitly declared default constructor
Test const t1 ;
^

"test.cpp", line 10: warning: variable "t2" was declared but never
referenced
Test t2( t1 ) ;
^

1 error detected in the compilation of "test.cpp".

$ g++ test.cpp
test.cpp: In function `int main()':
test.cpp:9: error: uninitialized const `t1'

The diagnostic is reasonable according to 8.5/p9.

But this diagnostic maybe is irrelative to our discussion,
since if I add the default constructor, all compilers
compile above example without any complain.

>
> That the signature of the compiler generated copy constructor is
> Test( Test const&) here, and that as in the initial case,
> overload resolution choses the template.
>


As I said just now, in the sense of standard, it is
unspecified behavior in my mind.

But I must confess the const form is the better choice
compared with the non-const form.

Francis Glassborow

unread,
Jul 25, 2006, 7:56:56 AM7/25/06
to
In article <44c55561$0$24894$9b4e...@newsread4.arcor-online.net>,
Matthias Hofmann <hof...@anvil-soft.com> writes

>"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
>news:1153732876.0...@75g2000cwc.googlegroups.com...
>
>> > As a general rule, I would say that you shouldn't overload
>> > functions if it will make a difference which one would be
>> > called.
>
>Why would you overload functions if it does not make a difference which one
>will be called?

Because there are often variant implementations depending on possible
arguments but they should all have the same semantic consequences.

--
Francis Glassborow ACCU
Author of 'You Can Do It!' and "You Can Program in C++"
see http://www.spellen.org/youcandoit
For project ideas and contributions: http://www.spellen.org/youcandoit/projects

Jiang

unread,
Jul 25, 2006, 9:53:39 AM7/25/06
to


Well, the point is, if you really care about this issue, then write
your own copy constructor explicitly is the only safe way to ensure the
same copy sematics in different TUs.

As for the template constructor, it can be used for types other than
the class itself, and franklly speaking now I am not sure what will
happen if the template parameter is the class itself.

kanze

unread,
Jul 25, 2006, 12:05:37 PM7/25/06
to
James Dennett wrote:
> Matthias Hofmann wrote:
>> "kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
>> news:1153732876.0...@75g2000cwc.googlegroups.com...

>>>> As a general rule, I would say that you shouldn't overload
>>>> functions if it will make a difference which one would be
>>>> called.

>> Why would you overload functions if it does not make a
>> difference which one will be called?

> (1) To allow calling with a wider range of argument types
> (2) For efficiency

> On the other hand, why would you design an interface such that
> a user has to consider the result of overload resolution in
> order to know which operation will be performed? If they
> operations are that different, they should have different
> names.

That's really what I was trying to say. You just expressed it a
lot better.

Of course, when it comes to constructors, we don't have much
choice concerning the name, and sometimes, we do end up having
to have overloads where the choice made by overload resolution
affects the semantics of the code.

I suspect that this is at least part of the motivation for
"std::string( size_t, char )", as opposed to the what would seem
more intuitive to me "std::string( char, size_t = 1 )"; given
the latter, something like "std::string( NULL )" would be
legal... and create a string with a length of 1, which is
probably not what the author wanted. (The argument would be
even stronger if "std::string( (char const*)0 )" were a legal
means of creating an empty string.)

--
James Kanze GABI Software
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

kanze

unread,
Jul 25, 2006, 12:07:35 PM7/25/06
to
Jiang wrote:

>> The signature of the compiler generated copy constructor
>> here will be Test( Test const& ). But you're right that
>> §12.8/5 could express it clearer. But I don't think that
>> there's any question about it. The signature will be Test(
>> Test const& ) unless at least one base class or member of
>> class type has a copy constructor whose signature does not
>> take the const.

>> Basically, if you consider the two bullets in §12.8/5, there
>> are no direct or virtual base classes, so all of the direct
>> or virtual base classes have the required copy constructor,
>> and there are no members of class type, so all of the
>> members of class type have the required copy constructor.

> As other rules in standard, the wording is like this:

> The implicitly-declared copy constructor ... will be

> X::X(const X&)

> if
> condition 1 here, and
> condition 2 here

> Otherwise, it will have form

> X::X(X &)

> Here the word "otherwise" is indeed problematic,

Not really. It's the condition that probably needs clearer
wording.

> since the class Test does not have any base classes and
> members, then the two specified conditions can not be
> satisfied.

I think that's the subtility you're missing. The conditions a
"each [...]" and "for all [...]". Both mean that if there is 1,
then 1 meets the condition, if there are 2, then 2 meet the
condition, and so on. And equally, if there are 0, then 0 meet
the condition. If a class has no non-static data members of
class type, then all zero of its non-static data members of
class type meet the condition.

> Thus, the default copy constructor should be the non-const
> form. That was what I read it.

I'm 100% sure that this isn't the intent. But I'll admit that
that is mainly because I've known C++ since well before the
standard was adopted, and it has always been this way.

I think that formulating the rule with an unless would be a lot
clearer:

The implicitly-declared copy constructor [...] will be

X::X(const X&)

unless one or more direct or virtual bases B or one or more
members of class type B has a copy constructor whose first
parameter is neither B& or const B&. Otherwise, it will be

X::X(X&)

[...

>> class Test { } ;

And required. Just goes to show that I should have tested my
code first.

> But this diagnostic maybe is irrelative to our discussion,
> since if I add the default constructor, all compilers compile
> above example without any complain.

Exactly. Change the first line in main to:

Test const t1 = Test() ;

and it compiles fine. More generally, since the problem is only
whether it compiles:

void
f( Test const& t1 )
{
Test t2( t1 ) ;
}

>> That the signature of the compiler generated copy
>> constructor is Test( Test const&) here, and that as in the
>> initial case, overload resolution choses the template.

> As I said just now, in the sense of standard, it is
> unspecified behavior in my mind.

> But I must confess the const form is the better choice
> compared with the non-const form.

I'm 100% sure that the const form is the intent. I also think
that after a careful analysis, it is the only way to interpret
the standard. I do think it could have been more clearly
expressed.

--
James Kanze GABI Software
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

kanze

unread,
Jul 25, 2006, 12:04:14 PM7/25/06
to
Matthias Hofmann wrote:
>>>> Curiously enough (and don't ask me why), the fact that the
>>>> expression has the same type in:
>>>> Test t2 = t1 ;
>>>> means that we are NOT performing a copy, whereas if it had a
>>>> different type, a copy would be required.

>>> How did you get to this conclusion?

>> Because §8.5/14 (fourth bullet, second sub-bullet) says so
>> explicitly.

> I cannot find any part in the text that is so explicit.

Sorry. It depends, of course, on what you understand by "copy".
The only real point is that something like "Test t2 = t1" obeys
the rules of direct-initialization (and not those of
copy-initialization) if t1 and t2 have the same type.

At the time I wrote it, I vaguely thought that there was a rule
saying that the copy in copy-initialization was done by the copy
constructor (if it was done at all, of course). In fact, of
course, the rule in the third sub-bullet says that the copy is
done by direct-initialization. As far as I can see now, there
is no place where the compiler automatically uses the copy
constructor---overload resolution is always involved. (Which
makes the first paragraph of §12.8 even less precise.)

> The second sub-bullet neither mentions the copy constructor,
> nor does it talk about an object being copied, which is
> actually just your argument. But the text in the sub-bullet
> that follows, which is the one that handles
> copy-initialization for different source and target types,
> does not require a copy either. The only term that comes close
> to it is a "temporary". Are temporary objects copies by
> definition?

It would be nice to know exactly what the standard does mean by
"copy". I think that the term mainly occurs in the less precise
parts of the standard. Things like the first paragraph of
§12.8, which is, I think, mainly meant to set the scene, and
explain what the section will explain in detail, and is not
meant to be a precise description of a particular behavior a
compiler is required to have.

>> My interpretation (and I don't think 8.5/14 makes sense
>> otherwise) is that when the standard speaks about copying, it is
>> speaking about cases where it explicitly says that an object
>> will be copied. In other cases, such as in the example code
>> here, the fact that the initialization expression happens to
>> have the same type as the target is more or less a coincidence;
>> from a standards perspective, it is not copying (although the
>> copy constructor definitly participates in overload resolution).

> That makes sense, although it is not intuitive.

Not at all. The only thing really supporting it is that §8.5/14
wouldn't make sense otherwise.

>> I agree that this interpretation doesn't really coincide
>> with what one would think of the word copy in normal English
>> use. But I guess I've grown so used to the standard using
>> words in special ways that it doesn't bother me too much.

> Direct-initialization is always direct-initialization, but
> copy-initialization is only sometimes copy-initialization,
> because sometimes it is also direct-initialization. That's the
> standard the way I know it... ;-)

Copy-initialization is a conversion followed by
direct-initialization. Except if it isn't (e.g. because the
types are the same and no conversion is necessary).

According to §8.5/14, of course. Because §8.5/12 would seem to
suggest that they are two opposing concepts.

As my mother would have said: clear as mud. (I don't know
whether that is a general English expression, or geographically
limited. My mother is from northern Georgia, and when I first
visited Great Britain, speaking English as I'd learned it from
her, I had to find people who spoke French in order to be
understood.)

>>> To me, the meaning of the term "copy" seems rather vague
>>> in this thread. For example, what is the difference
>>> between copying an object and initializing it with another
>>> object of the same type? If I understand 12.8/1 correctly,
>>> both should be the same.

>> I'm not sure that §12.8/1 is that clear about it. It
>> certainly initialization can be copying, and some
>> initializations definitly are copying. I don't think you
>> have to (or should) interpret it to mean that all
>> initialization is copying, or even all initialization with
>> the same type is copying.

> You mean that initialization with the same type is only
> sometimes copying? So when is it, and when is it not? And
> what do you mean when you say "copying", copying in the sense
> of the standard, or copying in the common English sense of the
> word?

What I mean is that I'm not sure myself what the standard means
by "copying". I tend to base my statements concerning behavior
on §8.5 for how the compiler resolves initialization, because
that section seem to be a very detailed list of the steps a
compiler should take, where all of the other places sited seem
to be vaguer with regards to initialization, and to treat it as
a secondary issue. §12.8, for example, makes some general
statements about "copying", but seems mainly concerned about
describing the exact cases when and when not a compiler should
generate the defaults, and the form and semantic of these
defaults. (Similarly, §8.5 doesn't even mention templates, but
it does refer to overload resolution, which is described in
detail in §13, and so on.)

>> The first part is obvious, I think; the second goes against
>> an intuitive interpretation of the word copying, but seems
>> to correspond best to the text in §8.5/14. And §8.5/12,
>> where the term "copy-initialization" is defined as "The
>> initialization that occurs in argument passing, function
>> return, throwing an exception, handling an exception, and
>> brace-enclosed initializer lists is called
>> <i>copy-initialization</i> and is equivalent to the form T x
>> = a;" The fact that copy-initialization is italicized here
>> means that this is the definition of the term. (Although
>> the standard then later specifies one particular case where
>> copy-initialization uses function overload resolution to
>> choose the constructor, rather than automatically using the
>> copy constructor.)

> 12.8/1 simply confuses me. It says that an object can be
> copied by initialization, but you say that not all
> initialization, even with the same type, is copying.

Me too. Strictly speaking, I guess you could say that "can"
doesn't mean "will" or "must be"; taken this way, the paragraph
says that copying will never take place except in initialization
or assignment. (But I'd generally use "may", and not "can", if
that were the case.) The word "copied" isn't in italics here,
so presumably, this isn't a definition. And I don't know of one
elsewhere, so presumably, the standard English meaning is in
effect.

But I don't see where §12.8/1 really says anything concrete
anyway. I think it's more a vague presentation: a "this is what
we're going to talk about in this section" sort of thing. And
that whatever it means by "copied" really doesn't matter,
because the exact rules for the behavior in each specific case
are deliminated elsewhere in the standard.

Whatever the intended meaning of "to copy" in §12.8/1, it seems
different from the intended meaning in §12.8/3.

--
James Kanze GABI Software

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

Matthias Hofmann

unread,
Jul 25, 2006, 1:53:51 PM7/25/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1153834098.8...@i42g2000cwa.googlegroups.com...

> > 12.8/1 simply confuses me. It says that an object can be
> > copied by initialization, but you say that not all
> > initialization, even with the same type, is copying.
>
> Me too. Strictly speaking, I guess you could say that "can"
> doesn't mean "will" or "must be"; taken this way, the paragraph
> says that copying will never take place except in initialization
> or assignment. (But I'd generally use "may", and not "can", if
> that were the case.) The word "copied" isn't in italics here,
> so presumably, this isn't a definition. And I don't know of one
> elsewhere, so presumably, the standard English meaning is in
> effect.

Just out of curiosity, I did a search within the standard to see if the word
"copy" is in italics anywhere. I found two places where it is: In 12.8/2:

"A non-template constructor for class X is a [i]copy[/i] constructor if its
first parameter [...]"

and in 12.8/9:

"A user-declared [i]copy[/i] assignment operator [...] is a non-static
non-template member function [...]"

I don't know if this implies that a copy can be made by either a copy
constructor or a copy assigment operator, but not in any other way? Section
20.1.3 about copy construction does not mention copy constructors in the
table of requirements for CopyConstructible objects.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

kanze

unread,
Jul 26, 2006, 9:39:00 AM7/26/06
to

> and in 12.8/9:

Interesting. I would have expected that the words "constructor"
and "assignment operator" also be in italics here, since that's
what I would think was being defined.

All in all, I wonder if a defect report wouldn't be in order.

--
James Kanze GABI Software
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

Stephan Tolksdorf

unread,
Jul 26, 2006, 11:11:58 AM7/26/06
to
kanze wrote:
> All in all, I wonder if a defect report wouldn't be in order.

As there is already work being done on the initialization semantics, it
might be an opportunity to clear up the relevant passages with regard to
copy construction -- something which is certainly desirable from an end
user's perspective. However, it would probably require someone familiar
with the current thinking of the working group to formulate a proposed
resolution because the issue seems hard to pinpoint.

Stephan

Matthias Hofmann

unread,
Jul 27, 2006, 10:27:40 AM7/27/06
to
"Stephan Tolksdorf" <ando...@gmx.de> schrieb im Newsbeitrag
news:ea7u9p$o3o$1...@news01.versatel.de...

> kanze wrote:
> > All in all, I wonder if a defect report wouldn't be in order.
>
> As there is already work being done on the initialization semantics, it
> might be an opportunity to clear up the relevant passages with regard to
> copy construction -- something which is certainly desirable from an end
> user's perspective. However, it would probably require someone familiar
> with the current thinking of the working group to formulate a proposed
> resolution because the issue seems hard to pinpoint.

Does anyone happen to know how this working group can be reached, so we can
direct their attendion towards this discussion? It might be easier for them
to understand our confusion than it might be for us to explain what our
actual problem is.

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

kanze

unread,
Jul 28, 2006, 7:56:42 AM7/28/06
to
Matthias Hofmann wrote:
> "Stephan Tolksdorf" <ando...@gmx.de> schrieb im Newsbeitrag
> news:ea7u9p$o3o$1...@news01.versatel.de...
> > kanze wrote:
> > > All in all, I wonder if a defect report wouldn't be in order.

> > As there is already work being done on the initialization
> > semantics, it might be an opportunity to clear up the
> > relevant passages with regard to copy construction --
> > something which is certainly desirable from an end user's
> > perspective. However, it would probably require someone
> > familiar with the current thinking of the working group to
> > formulate a proposed resolution because the issue seems hard
> > to pinpoint.

> Does anyone happen to know how this working group can be
> reached, so we can direct their attendion towards this
> discussion? It might be easier for them to understand our
> confusion than it might be for us to explain what our actual
> problem is.

Defect reports can be posted to comp.std.c++. And there's no
necessity to formulate a proposed resolution in them; just
pointing out the passages which aren't clear, or which are in
contradiction with other passages, should be enough.

--
James Kanze GABI Software
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

Matthias Hofmann

unread,
Jul 31, 2006, 9:00:52 AM7/31/06
to
"kanze" <ka...@gabi-soft.fr> schrieb im Newsbeitrag
news:1154077755.6...@75g2000cwc.googlegroups.com...

> > Does anyone happen to know how this working group can be
> > reached, so we can direct their attendion towards this
> > discussion? It might be easier for them to understand our
> > confusion than it might be for us to explain what our actual
> > problem is.
>
> Defect reports can be posted to comp.std.c++. And there's no
> necessity to formulate a proposed resolution in them; just
> pointing out the passages which aren't clear, or which are in
> contradiction with other passages, should be enough.

Ok, then can anyone help me summarize which passages have shown to be
unclear during this discussion? I can remember the following points:

- 12.8/1 is rather vague. In particular, no one seems to know how copying is
"conceptually" implemented by a copy constructor and copy assignment
operator.
- There is much confusion as to what "a copy" or "copying an object" means
in terms of the standard.
- 12.8/3 is very easy to misunderstand. It should be changed in such a way
that everybody will see that it only applies to the case mentioned in the
first sentence.
- Is there any reason that in 12.8/2 only the word "copy" is in italics? The
same goes for 12.8/9.

Anything else?

--
Matthias Hofmann
Anvil-Soft, CEO
http://www.anvil-soft.com - The Creators of Toilet Tycoon
http://www.anvil-soft.de - Die Macher des Klomanagers

[ See http://www.gotw.ca/resources/clcm.htm for info about ]

0 new messages