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

2021-12-13 00:00:00 templates c++ copy-constructor

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

I have a template class that has a template copy constructor. The problem is when I instantiate this class using another instance of this class with the same template type, my template copy constructor is not called. Why doesn't it match?

这是代码片段:

#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

但是如果我显式地编写了默认的复制构造函数(通过取消注释),那么输出就变成了

But if I explicitly write the default copy constructor (by uncommenting it), then the output becomes

default constructor
copy constructor

我真的不明白.我用我的本地编译器(Clang 500.2.79)和 这个 (GCC 4.9.2) 并得到相同的结果.

I really don't get it. I tested it with my local compiler (Clang 500.2.79) and with this one (GCC 4.9.2) and got the same result.

推荐答案

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

A copy constructor is of the form X(X& ) or (X const&) and will be provided for you by the compiler if you didn't declare one yourself (or a few other conditions which are not relevant here). You didn't, so implicitly we have the following set of candidates:

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

两者都适用

MyTemplateClass<int> instance2(instance);

两者都采用完全相同的参数.问题不在于您的复制构造函数模板不匹配.问题是隐式复制构造函数不是函数模板,在重载解析方面,非模板比模板特化更受欢迎.来自 [over.match.best],省略不相关的要点:

Both take the same exact arguments. The issue isn't that your copy constructor template doesn't match. The issue is that the implicit copy constructor is not a function template, and non-templates are preferred to template specializations when it comes to overload resolution. From [over.match.best], omitting the unrelated bullet points:

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

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,
― [...]

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

That's why it calls your implicit (and then, your explicit) copy constructor over your constructor template.

相关文章