Templated Copy Constructor, Fall T = T

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Antworten
PlainOldCJ
Beiträge: 11
Registriert: 03.12.2012, 20:56
Echter Name: Christian

Templated Copy Constructor, Fall T = T

Beitrag 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;
}
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Templated Copy Constructor, Fall T = T

Beitrag von dot »

Weil das per Definition kein Copy-Ctor ist und der Compiler darum einen generiert... ;)
PlainOldCJ
Beiträge: 11
Registriert: 03.12.2012, 20:56
Echter Name: Christian

Re: Templated Copy Constructor, Fall T = T

Beitrag 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?
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Templated Copy Constructor, Fall T = T

Beitrag 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... ;)
Benutzeravatar
Krishty
Establishment
Beiträge: 8268
Registriert: 26.02.2009, 11:18
Benutzertext: state is the enemy
Kontaktdaten:

Re: Templated Copy Constructor, Fall T = T

Beitrag 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?
seziert Ace Combat, Driver, und S.T.A.L.K.E.R.   —   rendert Sterne
PlainOldCJ
Beiträge: 11
Registriert: 03.12.2012, 20:56
Echter Name: Christian

Re: Templated Copy Constructor, Fall T = T

Beitrag von PlainOldCJ »

Hey.
Okay, das macht Sinn.
Vielen Dank dot! :)
Antworten