简体   繁体   中英

Templated Class “Copy Constructor”

I've come across this templated smart pointer class Cptr shown partially below, and I don't understand one of the method implementations and was hoping to get some input. My question is on 'Method 2', labeled below. Specifically, if Cptr is templated by T, what call syntax is available that allows 'Method 2' to be called, which appears, at least to me, to be a copy constructor, but I thought copy constructors are not templated.

template <class T> class Cptr
{
    public:

        /* Constructors ... */

        /* Getters ... */
        T* ptr() const { return p_; }
        long* cnt() const { return cnt_; }

        /* Copy Constructors? */
        //Method 1
        Cptr<T>(const Cptr<T>& i) 
            : ptr_(i.ptr()), cnt_(i.ptr())
        {
            std::cout << "M1" << std::endl;
            ++(*cnt);
        }

        //Method 2
        template <class S> Cptr(const Cptr<S>& i) 
            : ptr_(i.get()), cnt_(i.cnt())
        {
            std::cout << "M2" << std::endl;
            ++(*cnt_);
        }

    private:
        T* p_;
        int* cnt_;
};

int main(int argc, char* argv[])
{

    CPtr<int> A(new int(5));
    CPtr<int> B(A);

    std::cout << *(B.get()) << std::endl;

    return EXIT_SUCCESS;
}

I envisioned a call to method 2 like so:

Cptr<float> B( new float(1.1) );
Cptr<int> A(B); //error for different types

But the assignment of pointers of different types does not make much sense to me. Has anyone come across a method definition like 'Method 2' and if so what are the uses? Thanks very much for your time.

First of all, copy constructors can certainly be a template, loosely speaking. Technically, a copy constructor is a constructor from another instance of the same class, but you can certainly define a constructor that takes a reference to another class as a parameter.

However, the answer to your primary method is that "Method2" allows the smart pointer to be assigned from a smart pointer to a different class, as long as the implied type conversion is allowed:

class Base {};

class Derived : public Base {};

Cptr<Derived> d;

Cptr<Base> b=d; // "Method2" will be used here.

This smart pointer implementation allows a smart pointer to a derived class to be assigned to a smart pointer to the base class.

Normally, Cptr<Base> and Cptr<Derived> are two completely unrelated classes. Each template instance is a separate class. And you can't normally assign an instance of one class to an instance of a completely unrelated class, unless an appropriate conversion is available.

Just like you can assign an ordinary pointer to a derived class to a pointer to a base class, this smart pointer provides comparable functionality.

First of all, you are right. Copy constructors cannot be templates. §12.8/2 says (emphasis by myself):

A non-template constructor for class X is a copy constructor if its first parameter is of type X& , const X& , volatile X& or const volatile X& , and either there are no other parameters or else all other parameters have default arguments [...]

But method 2 is not a copy constructor, because Cptr<S> is a different class than Cptr<T> . It is just a normal constructor, not really much different to, say, Cptr(int i) or Cptr(std::string const& s) . And normal constructors can be templates.

Of course, you can assume that Cptr<U> will have the same members as Cptr<T> . That's what the implementation of the constructor does. It would not work, for example, if Cptr was specialised for that U and those members did not exist.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM