Question

I have a template class C. I want such a template copy constructor that it will resize the data array according to the size of the other class.

The following is a simple example. It works fine. However, notice that Constructor 2 and Constructor 3 are so similar, I am wondering whether it is possible to merge them as one?

Also, if I simple remove Constructor 3, then C<int> c3( c1 ) won't call Constructor 2, but will rather call a default copy constructor added by the compiler. This will result in the memory not being allocated properly.

template<typename T>
class C
{
public:
    T* val; 
    int size; 
public:

    C( int s = 0 ) {
        cout << "Constructor 1" << endl; 
        size = s; 
        val = ( size ) ? new T[size] : nullptr; 
    } 

    template<class T2>
    C( const C<T2>& c2 ) {
        cout << "Constructor 2" << endl; 
        size = c2.size; 
        val = ( size ) ? new T[size] : nullptr; 
    } 

    C( const C<T>& c2 ) {
        cout << "Constructor 3" << endl; 
        size = c2.size; 
        val = ( size ) ? new T[size] : nullptr; 
    } 

    ~C() {
        cout << "~C()" << endl; 
        delete[] val; 
        val = nullptr; 
    }
};

int main(void)
{
    C<int>   c1( 5 );
    C<float> c2( c1 );  
    C<int>   c3( c1 ); 

    return 0;
}

Output of the above function:

Constructor 1
Constructor 2
Constructor 3
~C()
~C()
~C()
Was it helpful?

Solution

Replace

template<class T2>
C( const C<T2>& c2 ) {
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = ( size ) ? new T[size] : nullptr; 
} 

C( const C<T>& c2 ) {
    cout << "Constructor 3" << endl; 
    size = c2.size; 
    val = ( size ) ? new T[size] : nullptr; 
} 

by

template<class T2>
C( const C<T2>& c2, int dummy) {
    cout << "Constructor 2" << endl; 
    size = c2.size; 
    val = ( size ) ? new T[size] : nullptr; 
}

template<class T2>
C( const C<T2>& c2 ) : C(c2, 0) {}

C( const C<T>& c2 ) : C(c2, 0) {} 

Update

You can just use:

C( int s = 0 ) {
    cout << "Constructor 1" << endl; 
    size = s; 
    val = ( size ) ? new T[size] : nullptr; 
} 

template<class T2>
C( const C<T2>& c2 ) : C(c2.size) {}

C( const C<T>& c2 ) : C(c2.size) {} 

and not need the second constructor.

OTHER TIPS

One would like to implement this with a C++11 delegating constructor. However due to ambiguity in if template paramaters are to the class or to the constructor, this is not possible in a straightforward manner. As a workaround one can factor out the common code into a helper function.

something like:

    template<class T2>
    C( const C<T2>& c2 ) {
        Copy<T2>(c2);
    } 

    C( const C<T>& c2 ) {
        Copy<T>(c2);
    }

private:
    template<class T2>
    void Copy( const C<T2>& c2 ) {
        cout << "Constructor 2" << endl; 
        size = c2.size; 
        val = ( size ) ? new T[size] : nullptr; 
    }
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top