Reputation: 33
While pursuing some errors, I stumbled upon the following behavior of initialization, which seems odd to me: While initialization checks for existing constructors, there seem to be cases were templates for fitting constructors are ignored. Consider for example the following program:
#include <iostream>
template<class T>
struct A {
A() {};
template<class S>
A(const A<S>& a) {std::cout << "constructor template used for A" << std::endl;};
};
template<class T>
struct B{
B() {};
B(const B<int>& b) {std::cout << "constructor used for B" << std::endl;};
};
int main() {
A<int> a;
B<int> b;
A<int> aa = a;
B<int> bb = b;
A<double> aaa = a;
}
For me, this produces the output
constructor used for B
constructor template used for A
this means it does not use the constructor in the third line of main. Why not? Is there a reason? Or is my syntax off somewhere? The template seems to work, as it is successfully used in the last line.
I know the example seems overly complicated, but various simplifications made the behavior I wanted to display go away. Also: A template specialization will be used by the initialization and is how I currently prevent this causing errors (where it caused errors in the first place).
I am sorry if my question is off in any way, I am not a programmer, I am not a native speaker and this is my first question, please forgive me.
Upvotes: 3
Views: 172
Reputation: 227410
The compiler provides an implicitly declared non-template copy constructor with signature equivalent to
A(const A& a);
because a template constructor is not considered as a user defined copy constructor, i.e. a copy constructor has to be a non-template.
The implicitly declared copy constructor is a better match in the overload resolution than the template version, and is the one that gets called when you copy construct an A<T>
from an A<T>
. This can be illustrated with a simple example, with a user defined A(const A&)
:
#include <iostream>
template<class T>
struct A
{
A() {};
A(const A& a) {
std::cout << "copy constructor used for A" << std::endl;
}
template<class S>
A(const A<S>& a) {
std::cout << "constructor template used for A" << std::endl;
}
};
int main()
{
A<int> ai;
A<double> ad = ai; / calls template conversion contructor
A<int> ai2 = ai; // calls copy constructor A(const A&);
}
Upvotes: 4
Reputation: 126432
Per Paragraph 12.8/7 of the C++11 Standard:
If the class definition does not explicitly declare a copy constructor, one is declared implicitly.
Moreover, per Paragraph 12.8/2:
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 (8.3.6).
Therefore, the compiler will generate an implicit copy constructor here that gets invoked during the execution of this line:
A<int> aa = a;
This explains why you do not see a corresponding output.
Upvotes: 4
Reputation: 18228
This is because templated ctor is not a copy ctor. See also https://stackoverflow.com/a/1249848/341065.
Upvotes: 0