我有一个模板类,它有一个模板复制构造函数。问题是当我使用具有相同模板类型的此类的另一个实例来实例化此类时,我的模板复制构造函数未被调用。为什么不匹配?
以下是代码段:
#include <iostream>
template <typename T>
class MyTemplateClass
{
public:
MyTemplateClass()
{
std::cout << "default constructor" << std::endl;
}
/*
MyTemplateClass(const MyTemplateClass<T>& other)
{
std::cout << "copy constructor" << std::endl;
}
*/
template <typename U>
MyTemplateClass(const MyTemplateClass<U>& other)
{
std::cout << "template copy constructor" << std::endl;
}
};
int main()
{
MyTemplateClass<int> instance;
MyTemplateClass<int> instance2(instance);
return EXIT_SUCCESS;
}
输出
default constructor
但是如果我明确地写了默认的复制构造函数(通过取消注释它),那么输出就变成了
default constructor
copy constructor
我真的不明白。我用我的本地编译器(Clang 500.2.79)和this one(GCC 4.9.2)测试了它并得到了相同的结果。
答案 0 :(得分:6)
复制构造函数的格式为X(X& )
或(X const&)
,如果您没有自己声明一个(或其他一些不是这样的条件),编译器会为您提供相关的)。你没有,所以我们有以下几套候选人:
MyTemplateClass(const MyTemplateClass&);
template <typename U> MyTemplateClass(const MyTemplateClass<U>&);
两者都可行
MyTemplateClass<int> instance2(instance);
两者都采用相同的确切论点。问题不在于您的复制构造函数模板与匹配。问题是隐式复制构造函数不是函数模板,并且在涉及重载解析时,非模板优先于模板特化。从[over.match.best]中,省略不相关的项目符号点:
鉴于这些定义,可行函数F1被定义为比另一个可行函数更好的函数 F2如果对于所有参数i,ICS i (F1)不是比ICS i (F2)更差的转换序列,然后是 - [...]
- F1不是功能模板专业化,F2是功能模板专业化,或者,如果不是,则为 - [...]
这就是为什么它会在构造函数模板上调用隐式(然后是你的显式)复制构造函数。
答案 1 :(得分:2)
如果代码中没有复制构造函数,编译器将隐式生成它。因此,当执行此行时:
MyTemplateClass<int> instance2(instance);
正在执行复制构造函数 ,但显然不是你的。我认为模板与它无关。
答案 2 :(得分:-1)
我认为REACHUS是对的,编译器正在生成一个默认的复制构造函数(就像它也可以使用非模板类),并且因为它更专业,所以优先考虑模板。您应该将“普通”复制构造函数设置为私有,或者更好,使用C ++ 11'deleted'关键字将该函数标记为不可用。编辑:这不编译,抱歉,我当时无法测试。