Re: Surprising constructor call
Am 30.08.2012 14:03, schrieb Daniel Kr?gler:
[Another attempt to reply after some weeks]
Unintentionally this was an older reply that already was
accepted. Here follows the actual response to the OPs last question.
Am 13.08.2012 21:40, schrieb Kaba:
> 13.8.2012 9:22, Daniel Kr?gler wrote:
>> You are providing an lvalue of type (non-const) A<int> to an
>> direct-initialization context. The compiler sees
>>
>> A<int>::A(const A&) // Copy constructor
>> A<int>::A(A&&) // Move constructor
>>
>> and additionally would deduce
>>
>> A<int>::A<A&>(A&) // No copy constructor, albeit it has the
>> // same effective signature than A<int>::A(A&)
>>
>> from the template constructor based on the non-const lvalue of
>> A<int>. The last one is a better match than any of the first two,
>> so the usual function-over-template rule cannot be applied here.
>>
>> Note that the last signature is no copy-constructor, because
>> copy/move-constructors won't be instantiated from templates (see
>> 12.8 p2+3).
>>
>> Note also that the restriction rule 12.8 p6 does not apply here,
>> because the instantiated signature is valid.
>
> Thanks for the informative reply. I am specifically looking at the
> 12.8 p7, which says that "A member function template is never
> instantiated to perform the copy of a class object to an object of
> its class type.". How is this not in effect?
Note that I was referring to C++11. The part that you quote has been
fixed during the C++11 standardization process, because this wording
was clearly misleading, see
http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1080
> For simplification, the r-value references can be left out of
> discussion since the same thing happens with l-value references:
>
> template <typename That>
> A(That& that)
> {
> std::cout << "Wait... what?" << std::endl;
> }
>
> The 12.8 p2 says: "A non-template constructor for class X is a copy
> constructor if its first parameter is of type X&, const X&,
> volatile X& or const volatile X&, and either there are no other
> parameters or else all other parameters have default arguments."
>
> So the _non-template_ part part will say that the template
> constructor is not a copy-constructor by definition.
Correct.
> So is it that the 12.8 p7 is not in effect because the template
> constructor is not a copy-constructor? In this case the 12.8 p7 is
> a bit like saying that a bicycle is never used to bake a cake,
> i.e. it says nothing at all.
As I described above, the previous 12.8 p7 was broken. The fixed
version is part of C++11 and this is what I meant by quoting "rule
12.8 p6 does not apply here", because it says:
"A declaration of a constructor for a class X is ill-formed if its
first parameter is of type (optionally cv-qualified) X and either
there are no other parameters or else all other parameters have
default arguments. A member function template is never instantiated to
produce such a constructor signature. [ Example:
struct S {
template<typename T> S(T);
S();
};
S g;
void h() {
S a(g); // does not instantiate the member template to produce
// S::S<S>(S);
// uses the implicitly declared copy constructor
}
?end example ]"
It does not apply here, because the generated signature
A<int>::A<A&>(A&)
does not fall into this category, it does *not* have a first parameter
of type (optionally cv-qualified) A.
HTH & Greetings from Bremen,
Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]