模板上的 C++ 模板复制构造函数 class
C++ template copy constructor on template class
我有一个模板 class,它有一个模板复制构造函数。问题是当我使用具有相同模板类型的此 class 的另一个实例实例化此 class 时,我的模板复制构造函数未被调用。为什么不匹配?
这是代码片段:
#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) 测试了它并得到了相同的结果。
当您的代码中没有复制构造函数时,编译器将隐式生成它。因此当这一行被执行时:
MyTemplateClass<int> instance2(instance);
正在执行一个复制构造函数,虽然显然不是你的。我认为模板与它无关。
在此处阅读更多相关信息:Implicitly-defined copy constructor
我认为REACHUS是对的。编译器正在生成一个默认的复制构造函数(就像它对非模板 class 一样)并且更喜欢它而不是你的模板,因为它更专业。
您应该将 "normal" 复制构造函数设为私有,或者更好,使用 C++11 'deleted' 关键字将函数标记为不可用。
但是,这无法编译。不好意思,当时没法测试。
复制构造函数的形式为 X(X& )
或 (X const&)
,如果您没有自己声明(或其他一些不相关的条件),编译器将为您提供这里)。你没有,所以隐含地我们有以下一组候选人:
MyTemplateClass(const MyTemplateClass&);
template <typename U> MyTemplateClass(const MyTemplateClass<U>&);
两者都适用于
MyTemplateClass<int> instance2(instance);
两者都采用完全相同的参数。问题不在于您的复制构造函数模板不 匹配 。问题在于隐式复制构造函数不是函数模板,在重载解析方面,非模板优于模板特化。来自 [over.match.best],省略不相关的要点:
Given these definitions, a viable function F1 is defined to be a better function than another viable function
F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
— F1 is not a function template specialization and F2 is a function template specialization, or, if not that,
— [...]
这就是它在构造函数模板上调用隐式(然后是显式)复制构造函数的原因。
我有一个模板 class,它有一个模板复制构造函数。问题是当我使用具有相同模板类型的此 class 的另一个实例实例化此 class 时,我的模板复制构造函数未被调用。为什么不匹配?
这是代码片段:
#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) 测试了它并得到了相同的结果。
当您的代码中没有复制构造函数时,编译器将隐式生成它。因此当这一行被执行时:
MyTemplateClass<int> instance2(instance);
正在执行一个复制构造函数,虽然显然不是你的。我认为模板与它无关。
在此处阅读更多相关信息:Implicitly-defined copy constructor
我认为REACHUS是对的。编译器正在生成一个默认的复制构造函数(就像它对非模板 class 一样)并且更喜欢它而不是你的模板,因为它更专业。
您应该将 "normal" 复制构造函数设为私有,或者更好,使用 C++11 'deleted' 关键字将函数标记为不可用。
但是,这无法编译。不好意思,当时没法测试。
复制构造函数的形式为 X(X& )
或 (X const&)
,如果您没有自己声明(或其他一些不相关的条件),编译器将为您提供这里)。你没有,所以隐含地我们有以下一组候选人:
MyTemplateClass(const MyTemplateClass&);
template <typename U> MyTemplateClass(const MyTemplateClass<U>&);
两者都适用于
MyTemplateClass<int> instance2(instance);
两者都采用完全相同的参数。问题不在于您的复制构造函数模板不 匹配 。问题在于隐式复制构造函数不是函数模板,在重载解析方面,非模板优于模板特化。来自 [over.match.best],省略不相关的要点:
Given these definitions, a viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then
— [...]
— F1 is not a function template specialization and F2 is a function template specialization, or, if not that,
— [...]
这就是它在构造函数模板上调用隐式(然后是显式)复制构造函数的原因。