初始化忽略构造函数模板

时间:2013-02-27 15:28:00

标签: c++ templates constructor initialization

在追求一些错误的同时,我偶然发现了以下初始化行为,这对我来说似乎很奇怪:在初始化检查现有构造函数时,似乎存在适用于构造函数的模板被忽略的情况。例如,考虑以下程序:

#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;
}

对我来说,这会产生输出

constructor used for B
constructor template used for A

这意味着它不使用main的第三行中的构造函数。为什么不?有原因吗?或者我的语法在哪里?模板似乎有效,因为它在最后一行成功使用。

我知道这个例子看起来过于复杂,但各种简化使我想要显示的行为消失了。另外:初始化将使用模板专业化,这是我当前如何防止这种错误(首先导致错误)。

如果我的问题以任何方式结束,我很抱歉,我不是程序员,我不是母语人士,这是我的第一个问题,请原谅我。

3 个答案:

答案 0 :(得分:4)

编译器提供隐式声明的非模板复制构造函数,其签名等效于

A(const A& a);

因为模板构造函数不被视为用户定义的复制构造函数,即复制构造函数必须是非模板。

隐式声明的复制构造函数在重载决策中比模板版本更好,并且是从A<T>复制构造A<T>时调用的复制构造函数。这可以用一个简单的例子来说明,用户定义了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&);
}

答案 1 :(得分:4)

根据C ++ 11标准的第12.8 / 7段:

  

如果类定义没有显式声明复制构造函数,则会隐式声明一个。

此外,根据第12.8 / 2段:

  

如果第一个参数的类型为X&amp;,const X&amp ;,则X类的非模板构造函数是一个复制构造函数,   挥发性X&amp;或const volatile X&amp;,并且没有其他参数或所有其他参数   有默认参数(8.3.6)。

因此,编译器将在此处生成一个隐式复制构造函数,该构造函数在执行此行期间被调用:

A<int> aa = a;

这解释了为什么您没有看到相应的输出。

答案 2 :(得分:0)

这是因为模板化的ctor不是复制者。另请参阅https://stackoverflow.com/a/1249848/341065