initialization ignores constructor templates

懵懂的女人 提交于 2019-12-10 21:24:34

问题


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.


回答1:


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&);
}



回答2:


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.




回答3:


This is because templated ctor is not a copy ctor. See also https://stackoverflow.com/a/1249848/341065.



来源:https://stackoverflow.com/questions/15115859/initialization-ignores-constructor-templates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!