2016-04-03 10 views
0

Ich möchte eine Struktur initialisieren sein Mitglied mit Forwarding-Argumente. Das kompiliert und funktioniert einwandfrei, außer wenn ich einen Destruktor deklariere und versuche, die Struktur von einer Funktion zurückzugeben (was meiner Meinung nach einen Kopierkonstruktor erfordert).implizites Kopieren einer Struktur mit Deklaration und Argument-Weiterleitung Konstruktoren

#include <utility> 

struct Foo 
{ 
    int val; 

    Foo(int val) : val(val) 
    { 
    } 
}; 

struct FooContainer 
{ 
    Foo member; 

    template<typename... Args> 
    FooContainer(Args&&... args) : 
     member(std::forward<Args>(args)...) 
    {} 

    ~FooContainer() {} 
}; 

FooContainer getFooContainer() 
{ 
    FooContainer retval(0); 
    return retval; 
} 

int main() {} 

Der Compiler Fehler ist:

example.cc: In constructor ‘FooContainer::FooContainer(Args&& ...) [with Args = FooContainer&]’: 
example.cc:27: instantiated from here 
example.cc:18: error: no matching function for call to ‘Foo::Foo(FooContainer&)’ 
example.cc:7: note: candidates are: Foo::Foo(int) 
example.cc:4: note:     Foo::Foo(const Foo&) 

Es sieht aus wie eine Kopie Konstruktor für FooContainer zu erzeugen versucht, aber nicht, weil es keine Möglichkeit hat Foo zu initialisieren. Aber wenn ich den FooContainer Konstruktor oder Destruktor entferne, kompiliert es fein. * Warum tut es das?

* auf http://cpp.sh/ mit GCC 4.9.2 sowieso. g ++ 4.4.3 unter Ubuntu gibt den gleichen Fehler, selbst wenn der Destruktor nicht deklariert ist.

+1

am Compiler error Suche, es sieht aus, als ob der Compiler nicht, ob weiß um den Kopierkonstruktor für Foo oder den 'Foo (int val)' -Konstruktor aufzurufen. Versuchen Sie, 'Foo (int val)' 'explizit 'zu machen. – user3147395

+0

Ich tat, und es änderte nichts - obwohl es den 'FooContainer' Konstruktor' explizit' machte. Vielen Dank! Jetzt um zu sehen, ob es alle meine Probleme in meinem Programm oder nur einige von ihnen behebt ... –

Antwort

1

Ich kann Ihnen nicht genau sagen, warum dies passiert (ein Standard-Experte wird dazu in der Lage sein), aber das Problem wird tatsächlich verursacht, weil Sie einen benutzerdefinierten Destruktor definiert haben.

entfernen, dass und das Problem verschwindet (die Regel-of-Null sowieso verwenden wollen, nicht wahr?)

Wenn Sie die destructor haben müssen und es nicht Refactoring kann aus irgendeinem Grund entfernt, dann ersetzen Der Move-Konstruktor (den Sie implizit durch Bereitstellung eines Destruktors gelöscht haben) wird es ebenfalls lösen.

Lösung 1 - Verwendung der Regel von 0:

#include <utility> 

struct Foo 
{ 
    int val; 

    Foo(int val) : val(val) 
    { 
    } 
}; 

struct FooContainer 
{ 
    Foo member; 

    template<typename... Args> 
    FooContainer(Args&&... args) : 
    member(std::forward<Args>(args)...) 
    {} 

// ~FooContainer() {} 
}; 

FooContainer getFooContainer() 
{ 
    FooContainer retval(0); 
    return retval; 
} 

int main() {} 

Lösung 2 - Verwendung der Regel von 5:

#include <utility> 

struct Foo 
{ 
    int val; 

    Foo(int val) : val(val) 
    { 
    } 
}; 

struct FooContainer 
{ 
    Foo member; 

    template<typename... Args> 
    FooContainer(Args&&... args) : 
    member(std::forward<Args>(args)...) 
    {} 

    FooContainer(const FooContainer&) = default; 
    FooContainer(FooContainer&&) = default; 
    FooContainer& operator=(const FooContainer&) = default; 
    FooContainer& operator=(FooContainer&&) = default; 

    ~FooContainer() {} 
}; 

FooContainer getFooContainer() 
{ 
    FooContainer retval(0); 
    return retval; 
} 

int main() {}