Why doesn't the standard consider a template constructor as a copy constructor?

后端 未结 3 1854
你的背包
你的背包 2021-02-05 02:03

Here\'s the definition of copy constructor, [class.copy.ctor/1]:

A non-template constructor for class X is a copy constructor if its first parameter is of

相关标签:
3条回答
  • 2021-02-05 02:37

    A copy constructor is of the form X(X& ) or (X const&), and it will be provided for you by the compiler if you didn't declare one yourself. Non-template comes here probably due to issues if you use template classes.

    Let's say there is a template class that has a template copy constructor. The problem is that when you instantiate that class using another instance of this class with the same template type, your template copy constructor will not be called.

    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.

    Source: C++ template copy constructor on template class

    0 讨论(0)
  • 2021-02-05 02:40

    Why is the "non-template" requirement there in the text?

    Given it were different and copy constructors could be templates. How could a non-copy constructor not be ambiguous in the presence of a copy constructor template? Consider this:

    struct Foo {
       // ctor template: clearly useful and necessary
       template <typename T>
          Foo(const T&) {}
    
       // copy ctor: same signature! can't work
       template <typename T>
          Foo(const T &) {}
    };
    

    Besides, constructing a Foo from an object that is not a Foo can be achieved by either conversion or ordinary construction, but allowing for copy-construction from a non-Foo object changes the notion of copying to copying including conversion. But this can already be implemented with the existing scheme (conversion or non-copy construction).

    In this example, here will be printed. So it seems that my template constructor is a copy constructor

    The example that you show doesn't invoke copy construction, but an ordinary, implicit construction. If you change the constructor template to

    template <typename T>
    Foo(const T &) {
    //  ^^^^^
        printf("here\n");
    }
    

    then Foo b = a; results in the compiler-generated copy constructor being called. Note that the copy ctor generated by the compiler has this signature:

    Foo(const Foo&);
    

    This requires adding a const-qualifier to a in Foo b = a;. The original constructor template Foo(T&) in your snippet is a better match, as no const-qualifier is added.

    0 讨论(0)
  • 2021-02-05 02:50

    Let's put templates aside for a second. If a class doesn't declare a copy constructor, an implicitly defaulted one is generated. It may be defined as deleted, but it's defaulted nonetheless.

    A member template is not a member function. Members are instantiated from it only when needed.

    So how can a compiler know from the class definition alone whether or not a specialization with T = Foo will ever be needed? It can't. But it's exactly that on which it needs to base a decision of how to handle a potential need for an implicitly defaulted copy constructor (AND move constructor). That becomes messy.

    The easiest approach is to exclude templates. We'll always have some copy constructor anyway, it will do the correct thingTM by default, and will be favored by overload resolution because it's not instantiated from a template.

    0 讨论(0)
提交回复
热议问题