Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ template copy constructor on template class

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?

Here is the code snippet:

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

The output is

default constructor

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

default constructor
copy constructor

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.

like image 277
Jairard Avatar asked Sep 12 '15 10:09

Jairard


2 Answers

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>&);

Both are viable for

MyTemplateClass<int> instance2(instance);

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:

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.

like image 64
Barry Avatar answered Oct 09 '22 06:10

Barry


When you do not have a copy constructor in you code, the compiler will implicitly generate it. Therefore when this line is executed:

MyTemplateClass<int> instance2(instance);

A copy constructor is being executed, though obviously not yours. I think that templating has nothing to do with it.

Read more about it here: Implicitly-defined copy constructor

like image 42
syntagma Avatar answered Oct 09 '22 07:10

syntagma