2012-06-14 19 views
8

W poniższym kodzie konstruktor variadic jest wywoływany dwa razy. Jak mogę uzyskać wywołanie konstruktora kopiowania zamiast wersji argumentów konstruktora variadic, gdy jest to właściwe?Jak uzyskać wywołanie konstruktora kopiowania za pomocą konstruktora variadic?

#include <iostream> 

struct Foo 
{ 
    Foo(const Foo &) 
    { 
     std::cout << "copy constructor\n"; 
    } 

    template<typename... Args> 
    Foo(Args&&... args) 
    { 
     std::cout << "variadic constructor\n"; 
    } 

    std::string message; 
}; 

int main() 
{ 
    Foo f1; 
    Foo f2(f1); // this calls the variadic constructor, but I want the copy constructor. 
} 

Odpowiedz

9

Faktycznie nie ma to nic wspólnego z faktem, że konstruktor jest variadic. Poniższa klasa z non-zmiennej liczbie argumentów szablonu konstruktora wykazuje ten sam problem:

struct Foo 
{ 
    Foo() { } 

    Foo(const Foo& x) 
    { 
     std::cout << "copy constructor\n"; 
    } 

    template <typename T> 
    Foo(T&& x) 
    { 
     std::cout << "template constructor\n"; 
    } 

}; 

Problem polega na tym, że szablon konstruktor jest lepszy mecz. Aby wywołać konstruktora kopiowania, wymagana jest konwersja kwalifikowania, aby powiązać nieokreśloną wartość l: f1 do const Foo& (należy dodać kwalifikację const).

Aby połączyć szablon konstruktora, nie są wymagane żadne konwersje: T można wywnioskować do Foo&, który po nawiązaniu zapadającego (Foo& && ->Foo&), daje parametr x typ Foo&.

Można obejść ten problem, udostępniając drugi konstruktor kopii, który ma nieodstawiony parametr odniesienia lvalue Foo&.

+1

Jest trochę więcej do niego, a mianowicie zwijanie referencji (jak to się nazywa?), Tj. 'T &&&' => 'T &', ponieważ w przeciwnym razie wartość l ("f1") nie mogłaby się połączyć z 'T &&'. –

4

tylko służy przeciążeniu ścisłym dopasowaniu, to znaczy jedna z nie- constFoo&, oprócz konwencjonalnego konstruktora kopii. Następnie możesz przekazać połączenie przez jawną obsadę:

Foo(Foo& other) : Foo(static_cast<Foo const&>(other)) { } 
Powiązane problemy