2015-11-10 15 views
5

Kiedy używam unique_ptr jako typ zwracany, otrzymuję kompilator błędu C2280:Czy mogę używać inteligentnych wskaźników C++ 11 jako typu zwracanego w C++ Actor Framework?

'caf::detail::tuple_vals<std::unique_ptr<A,std::default_delete<_Ty>>>::tuple_vals(const caf::detail::tuple_vals<std::unique_ptr<_Ty,std::default_delete<_Ty>>> &)': attempting to reference a deleted function include\caf\detail\tuple_vals.hpp 102 

Oto niektóre przykładowy kod, który ilustruje problem (zmodyfikowany z jednego z przykładów Aktor ramowych C++):

#include <iostream> 
#include "caf/all.hpp" 

using namespace caf; 
using namespace std; 

class A 
{ 
public: 
    int a; 

    A(int a) 
    { 
     this->a = a; 
    } 
}; 

using a_type = typed_actor<replies_to<int>::with<unique_ptr<A>>>; 

a_type::behavior_type a_behavior(a_type::pointer self) 
{ 
    return 
    { 
     [self](const int& a) -> unique_ptr<A> 
     { 
      return make_unique<A>(5); 
     } 
    }; 
} 

void tester(event_based_actor* self, const a_type& testee) 
{ 
    self->link_to(testee); 
    // will be invoked if we receive an unexpected response message 
    self->on_sync_failure(
     [=] 
     { 
      aout(self) << "AUT (actor under test) failed" << endl; 
      self->quit(exit_reason::user_shutdown); 
     }); 
    self->sync_send(testee, 5).then(
     [=](unique_ptr<A> a) 
     { 
      if(a->a == 5) 
      { 
       aout(self) << "AUT success" << endl; 
      } 

      self->send_exit(testee, exit_reason::user_shutdown); 
     } 
    ); 
} 
+0

Wszystkie typy wiadomości muszą być regularne, tzn. Mieć semantykę wartości. Środowisko wykonawcze wywołuje konstruktora kopiowania tylko wtedy, gdy * odłącza * wiadomość, która pojawia się, gdy próbuje uzyskać nie stały dostęp do wartości komunikatu z liczbą odwołań większą niż 1. – mavam

+0

@ MatthiasVallentin, jeśli rozumiem co mówisz, wtedy mój odpowiedź poniżej jest niepoprawna (po prostu się kompiluje). Jeśli dodasz swój komentarz do odpowiedzi, z przyjemnością go zaakceptuję! –

Odpowiedz

4

CAF wymaga, aby każdy typ wiadomości był regularny. Oznacza to, że musi dostarczyć konstruktora kopii, który nie ma. Dlatego kompilator narzeka.

Wiadomości mają implementację kopiowania przy zapisie. Możesz tanio skopiować pojedynczą wiadomość, ponieważ po prostu potrąca wewnętrznie licznik referencji. W dowolnym momencie możesz wykonać stały dostęp do elementów komunikatu. Część "zapisu" kopiowania na zapis kopie się tylko wtedy, gdy liczba odwołań do wiadomości jest większa niż 1 i żądasz dostępu niestanowiącego. W tym momencie środowisko wykonawcze wywołuje konstruktor kopiowania zawartego typu, aby utworzyć nową wiadomość.

Jeśli CAF bezwarunkowo wykonałby tę kopię, niezależnie od licznika referencyjnego, nie byłoby możliwe wydajne wspieranie programowania przepływu danych, gdy aktor odbiera komunikat, modyfikuje jego zawartość i przekazuje dalej do następnego etapu.

Pomyśl o wiadomościach jako o kontenerach wskaźnikowych: zawarte elementy są przydzielane w wolnym sklepie. Przechowywanie wskaźnika w wiadomości jest zwykle wadą projektową. Podwójne opakowanie również niepotrzebnie akcentuje przydział.

Ponieważ możesz elastycznie przekierowywać wiadomości, unikasz tworzenia pojedynczej wiadomości i możesz użyć zawartej wartości w różnych kontekstach.

2

Tak, C++ Actor Framework pozwala na inteligentne wskaźniki w komunikatach zwrotnych, ale nie w postaci unique_ptr.

Implementacja C++ Actor Framework obecnie tworzy kopię wiadomości i dereferencje unique_ptr, powodując błąd kompilatora.

Zamiast używać unique_ptr, należy zamiast tego użyć shared_ptr. Licznik odwołań będzie wynosił 2 podczas modyfikowania przykładowego kodu pytania. Użyłem również niestandardowej funkcji usuwania, aby sprawdzić, czy pamięć została zwolniona zgodnie z oczekiwaniami, pomimo utworzenia drugiego share_ptr.

Powiązane problemy