模板类上的c++模板复制构造函数

C++ template copy constructor on template class

本文关键字:复制 构造函数 c++      更新时间:2023-10-16

我有一个模板类,它有一个模板复制构造函数。问题是,当我使用具有相同模板类型的该类的另一个实例实例化该类时,不会调用模板复制构造函数。为什么不匹配?

下面是代码片段:
#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)和这个编译器(GCC 4.9.2)测试了它,得到了相同的结果。

复制构造函数的形式为X(X& )(X const&),如果您没有自己声明一个(或其他一些与此无关的条件),则编译器将为您提供。你没有,所以我们隐式地有以下候选集合:

MyTemplateClass(const MyTemplateClass&);
template <typename U> MyTemplateClass(const MyTemplateClass<U>&);

对于

都是可行的
MyTemplateClass<int> instance2(instance);

都接受完全相同的实参。问题不在于复制构造函数模板与不匹配。问题是隐式复制构造函数不是函数模板,当涉及到重载解析时,非模板优于模板专门化。从[over.match。最好],省略不相关的要点:

给定这些定义,一个可行函数F1被定义为比另一个可行函数更好的函数F2如果对于所有参数i, ICSi(F1)不是比ICSi(F2)更差的转换序列,然后
- - - - - -[…]
- F1不是函数模板专门化,F2是函数模板专门化,或者,如果不是,
- - - - - -[…]

这就是它在构造函数模板上调用隐式(然后是显式)复制构造函数的原因。

当代码中没有复制构造函数时,编译器将隐式生成它。因此,当执行这一行时:

MyTemplateClass<int> instance2(instance);

复制构造函数正在执行,但显然不是你的。我认为这与模板无关。

隐式定义复制构造函数

我认为REACHUS是对的。编译器正在生成一个默认的复制构造函数(就像它对非模板类一样),并且更喜欢它而不是你的模板,因为它更专门化。

你应该使你的"普通"复制构造函数私有,或者更好的是,使用c++ 11的"deleted"关键字将函数标记为不可用。

但是,这不能编译。对不起,我当时无法测试它