Seite 1 von 1

Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 15:31
von PlainOldCJ
Hi,

warum wird im nachfolgenden Quelltext der Fall

Code: Alles auswählen

Pointer<B> ptr0(...); Pointer<B> ptr1(ptr0);
nicht von dem templated Copy-Constructor abgedeckt? Stattdessen muss
der Copy-Constructor für einen Pointer gleichen Typs explicit hingeschrieben werden,
sonst erstellt der Compiler (g++ und msc) einen Default-Constructor für den problematischen
Fall.

Hier der Quelltext

Code: Alles auswählen

// #define NONTEMPLATE_CTOR 

#include <iostream>

template<typename T>
class Pointer {
    template<typename U> friend class Pointer;
private:
    T*          _raw;
    unsigned*   _cnt;
public:
    Pointer(void) { }

    Pointer(T* const raw) : _raw(raw), _cnt(new unsigned(1)) { }

#ifdef NONTEMPLATE_CTOR
    Pointer(const Pointer& other) : _raw(other._raw), _cnt(other._cnt) {
        if(_cnt) (*_cnt)++;
    }
#endif

    template<typename U>
    Pointer(const Pointer<U>& other) : _raw(other._raw), _cnt(other._cnt) {
        if(_cnt) (*_cnt)++;
    }

    const T* Raw(void) const { return _raw; }
    unsigned Count(void) const { return *_cnt; }
};

template<class T>
std::ostream& operator<<(std::ostream& stream, const Pointer<T>& ptr) {
    stream << "[" << ptr.Raw() << ", " << ptr.Count() << "]";
    return stream;
}

struct A {
    virtual int Val(void) const { return 10; }
};

struct B : A {
    int Val(void) const { return 20; }
};

int main(int argc, char* argv[]) {
    B* raw = new B();
    Pointer<B> ptr0(raw);

    std::cout << "ptr0 = " << ptr0 << std::endl;

    Pointer<B> ptr1(ptr0);

    std::cout << "ptr0 = " << ptr0 << std::endl;
    std::cout << "ptr1 = " << ptr1 << std::endl;

    Pointer<A> ptr2(ptr0);

    std::cout << "ptr0 = " << ptr0 << std::endl;
    std::cout << "ptr1 = " << ptr1 << std::endl;
    std::cout << "ptr2 = " << ptr2 << std::endl;

    return 0;
}

Re: Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 15:59
von dot
Weil das per Definition kein Copy-Ctor ist und der Compiler darum einen generiert... ;)

Re: Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 17:22
von PlainOldCJ
Okay, eine Definition als Erklärung ist super :) Danke für die schnelle Antwort!
Allerdings hätte ich in dem Fall schon eine Warnung erwartet, weil ein Aufruf
von Pointer(Pointer& other) dann doch mehrdeutig ist?

Re: Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 17:50
von dot
Nein ist er nicht. Instanzen von Pointer haben ja einen Copy-Ctor, nur eben den implizit vom Compiler generierten (weil es keinen Benutzerdefinierten gibt, da ein template nicht als Copy-Ctor gilt). Entsprechend den Overlad Resolution Rules werden non-templates gegenüber templates bevorzugt und daher wird ganz eindeutig der compilergenerierte Copy-Ctor aufgerufen... ;)

Re: Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 22:05
von Krishty
Unter GCC mal mit = delete des automatisch erzeugten Kopierk’tors versucht? Oder mit einer Referenz als Attribut, so dass der Compiler keinen Kopierk’tor erzeugen kann?

Re: Templated Copy Constructor, Fall T = T

Verfasst: 07.02.2013, 22:05
von PlainOldCJ
Hey.
Okay, das macht Sinn.
Vielen Dank dot! :)