footy
footy

Reputation: 5911

Copy constructor for templates

Copy constructor is failing in the following code. I have clipped the code for clarity

#include <iostream>
#include <stdio.h>
#include <assert.h>

namespace my {
    template <class T>
    class Sptr {
    private:
        //some kind of pointer
            //one to current obj
        T* obj;
.
.
.
    public:
.
.
.

        Sptr(const Sptr &);

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

.
.
.
};//Class ends

    template <typename T>
    template <typename U> 
    Sptr<T>::Sptr(U* u) {
        //do something
    }

    template <typename T>
    Sptr<T>::Sptr(const Sptr<T> &copyObj) {
        //do copy constructor stuff
    }
.
.
.
}

using namespace std;
using namespace my;
/* Basic Tests 1 ================================================================================ */
size_t AllocatedSpace;

class Base1 {
    protected:
        Base1() : derived_destructor_called(false) {
            printf("Base1::Base1()\n");
        }
    private:
        Base1(const Base1 &); // Disallow.
        Base1 &operator=(const Base1 &); // Disallow.
    public:
        virtual ~Base1() {
            printf("Base1::~Base1()\n");
            assert(derived_destructor_called);
        }
    protected:
        bool derived_destructor_called;
};

class Derived : public Base1 {
        friend void basic_tests_1();
    private:
        Derived() {}
        Derived(const Derived &); // Disallow.
        Derived &operator=(const Derived &); // Disallow.
    public:
        ~Derived() {
            printf("Derived::~Derived()\n");
            derived_destructor_called = true;
        }
        int value;
};

This test code line produces error Sptr<Base1> sp3(sp);

void basic_tests_1() {


    //size_t base = AllocatedSpace;

    // Test deleting through original class.
    {
        // Base1 assigned from Sptr<Derived>.
        {
            Sptr<Base1> sp2;
            {
                Sptr<Derived> sp(new Derived);
                // Test template copy constructor.
                Sptr<Base1> sp3(sp);
                sp2 = sp;
                sp2 = sp2;
            }
        }
    }
}

Error:

/tmp/ccKrn1xG.o: In function `basic_tests_1()':
Sptr.cpp:(.text+0x81): undefined reference to `my::Sptr<Base1>::Sptr<Derived>(my::Sptr<Derived> const&)'
collect2: error: ld returned 1 exit status

Upvotes: 0

Views: 2813

Answers (3)

didierc
didierc

Reputation: 14730

You don't have the definition of the required constructor, only the declaration:

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

You need to define it, either inline within the class definition or ouside, like the following:

template <typename T>
template <typename U> 
Sptr<T>::Sptr(const Sptr<U> &u) {
    // do something
}

Upvotes: 1

Tushar
Tushar

Reputation: 357

Shouldn't it be

template <typename T>
template <typename U> 
Sptr<T>::Sptr(const U& u) {
    //do something
}

instead of

template <typename T>
template <typename U> 
Sptr<T>::Sptr(U* u) {
    //do something
}

Upvotes: 0

Jonathan Wakely
Jonathan Wakely

Reputation: 171303

You've declared this constructor in the class:

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

But you haven't shown a definition. The error message says you never defined it. My guess is the error message is correct. Try fixing that.

Upvotes: 2

Related Questions