2016-07-28 17 views
0

Nehmen Sie die folgendenzwingt templatized Konstruktor über Compiler erzeugte Kopie-Konstruktor

template<class T> 
struct Foo { 
    Foo(){} 

    // a template constructor "generalized" over related types 
    template<class U> 
    Foo(Foo<U> const&) { 
     std::cout << 1; 
    } 

    // copy constructor 
    Foo(Foo const&) { 
     std::cout << 2; 
    } 
}; 

und seine Benutzer:

void main() { 
    Foo<int> f1; 
    Foo<const int> f2(f1); // prints 1 
    Foo<const int> f3(f2); // prints 2 
} 

Auch ohne die explizite Copykonstruktor, Compiler generiert ein und verwendet diese für f3(f2).

Gibt es eine Möglichkeit, die Überladung der Vorlage zu erzwingen? Zum Beispiel, kann der Copy-Konstruktor SFINAE'd out sein? Dies geschieht, um eine Code-Duplizierung zu vermeiden, da es interessanterweise scheinbar keine Möglichkeit gibt, delegierende Konstruktoren zu verwenden (Delegieren vom Kopierkonstruktor an die Vorlage).

+0

Nein, ist, dass nicht die gleiche, und es macht 'f3 (f2)' einen Fehler, da die Überladungsauflösung noch den Copykonstruktor und Fehler, wie 'delete'd nimmt. (Kommentar Ich antwortete fragte, ob 'löschen 'ist eine Option) – sly

Antwort

5

Eine Konstruktorvorlage kann niemals ein Kopierkonstruktor sein. Wenn Sie also keinen Konstruktor definieren, wird der Compiler dies implizit für Sie tun, wie Sie herausgefunden haben.

Eine Problemumgehung, um Code-Duplikation zu vermeiden, besteht darin, einen dritten Konstruktor zu definieren und ihn von beiden oben gezeigten Konstruktoren zu delegieren.

template<class T> 
struct Foo { 
    Foo(){} 

    struct tag{}; 

    // a template constructor "generalized" over related types 
    template<class U> 
    Foo(Foo<U> const& f) 
    : Foo(tag{}, f) 
    { 
     std::cout << 1 << '\n'; 
    } 

    // copy constructor 
    Foo(Foo const& f) 
    : Foo(tag{}, f) 
    { 
     std::cout << 2 << '\n'; 
    } 

private: 
    template<class U> 
    Foo(tag, Foo<U> const&) 
    { 
     std::cout << 3 << '\n'; 
    } 
}; 

Live demo

+0

interessanten Vorschlag. tatsächlich löst sich der praktische Anwendungsfall gut. ist jedoch keine direkte Antwort auf die Frage "Kann der Kopierkonstruktor deaktiviert werden?" (suchte nach einer nicht impliziten Version mit einem default sfinaed-Argument usw. - vielleicht ist die Antwort nein). An dieser Stelle denke ich ... – sly

+2

@sly Ich sehe nicht, wie Sie den Kopierkonstruktor SFINAE-deaktivieren können. Es handelt sich nicht um eine Vorlage, es gibt also keinen Abzug, der für SFINAE notwendig ist. – Praetorian