2012-08-01 14 views
15
//------------------------------------------------------------------------------ 
struct A 
{ 
    A(){} 
    A(A&&){} 
    A& operator=(A&&){return *this;} 
    void operator()(){} 

private: 
    A(const A&); 
    A& operator=(const A&); 

    int x; 
}; 

//------------------------------------------------------------------------------ 
int main() 
{ 
    A a; 
    std::function<void()> func(std::move(a)); 
} 

„A :: A”: nie ma dostępu do prywatnych członka zadeklarowana w klasie „A”Dlaczego C++ 11 nie przenosi niezideikowalnego funktora do funkcji std ::?

Wydaje się, że kiedy coś uchwycić poprzez odniesienie lub const mogę zrobić non-copyable lambda. Jednak kiedy to zrobię, to faktycznie działa, aby dać to std::function.

+1

Jako [obejście] (https://gist.github.com/vmilea/5815777) można umieścić adapter nadający się do kopiowania między std :: function i functor. Adapter ma konstruktor kopiowania obojętnego (przesuń na kopię) i zgłasza, jeśli został skopiowany. –

Odpowiedz

19

Krótka odpowiedź brzmi, że specyfikacja C++ 11 wymaga, aby numer A był CopyConstructible używany z std::function.

Odpowiedź jest długa, ponieważ std::function wymazuje typ twojego funktora w konstruktorze. Aby to zrobić, std::function musi uzyskać dostęp do niektórych członków funktora za pośrednictwem funkcji wirtualnych. Należą do nich operator połączenia, konstruktor kopii i destruktor. A ponieważ są one dostępne za pośrednictwem wywołania wirtualnego, są one "używane" niezależnie od tego, czy faktycznie używasz konstruktora kopiowania, destruktora lub operatora połączenia w trybie std::function.

+0

Popraw mnie, jeśli się mylę (i prawdopodobnie jestem), ale do korzystania z funkcji wirtualnych potrzebujesz vtable, a więc klasy bazowej. Która klasa bazowa w tym przypadku? – akappa

+5

Zobacz http://stackoverflow.com/questions/6324694/type-erasure-in-c-how-boostshared-ptr-and-boostfunction-work, aby dowiedzieć się, jak działa funkcja usuwania tekstu. Klasa podstawowa to szczegół implementacji funkcji std ::. Klasa pochodna jest również szczegółem implementacji, ale jest również szablonowana na dostarczonym funktorze. –

+0

bardzo interesujące, dziękuję. – akappa

-1

To błąd w Visual Studio. Próbuje usunąć kopię (gdy faktycznie powinna próbować usunąć ruch), co wymaga dostępnego konstruktora kopii. Najlepszym rozwiązaniem jest po prostu zadeklarowanie operatora kopiowania/operatora przypisania i nigdy go nie definiować. Klasa nadal będzie nie do kopiowania, ale kod się skompiluje, ponieważ VS nigdy nie będzie próbował wywołać konstruktora kopiowania.

+3

Najwyraźniej próbuje wywołać procedurę ctorowania, jeśli zrobię to, co sugerujesz, ponieważ otrzymuję nierozwiązany problem zewnętrzny. – David

+0

@Dave: Tak, dlatego jest to * błąd *. Standard mówi, że powinno być dozwolone, ale VS nie robi tego dobrze. –

+0

@NicolBolas To dobrze, ale jego sugestia obejścia problemu nie zadziałała. Nie wolno mi tak mówić? (Doceniam odpowiedź za pośrednictwem DeadMG, dzięki) – David

Powiązane problemy