2016-07-07 11 views
5

Mam problem z obejściem tego. Załóżmy, że mam ten wektorKonwersja z polimorfizmu shared_ptr na weak_ptr

std::vector<std::shared_ptr<Car>> cars; 

Samochód jest klasą abstrakcyjną. Chcę móc zwracać słabe wskaźniki różnych typów, więc wykonuję następujące czynności.

template<typename T> 
    std::weak_ptr<T> GetCar() 
    { 
     for (std::vector<std::shared_ptr<Car>>::iterator it = cars.begin(); it != cars.end(); ++it) 
     { 
      T* derived = dynamic_cast<T*>((*it).get()); 
      if (derived != nullptr) 
      { 
       std::weak_ptr<T> carPointer = *it; 
       return carPointer; 
      } 
     } 
     return std::weak_ptr<T>(); 
    } 

Otrzymuję następujący błąd, gdy próbuję użyć funkcji z klasą, która dziedziczy z samochodu. Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>' Na żądanie może nie być prawidłowego samochodu. Próbowałem użyć boost :: optional, ale nie radzi sobie z polimorfizmem. Mogę iść z surowymi wskazówkami, jeśli nie mogę tego zrobić.

+1

Typ wskazywany przez 'shared_ptr' i' weak_ptr' musi być taki sam. Zrobiłbym to w trzech krokach: zwróć 'weak_ptr ' następnie przekształć go w 'shared_ptr ', a następnie w 'T *'. –

+0

Dzięki za szybką odpowiedź @MarkRansom Mmm. Jest to funkcja użytkownika biblioteki, więc wolałbym nie udostępniać programisty, który mógłby z niego korzystać. Powinienem tak powiedzieć, mój zły. Czy poleciłbyś pracę tylko z surowymi wskazówkami, aby móc zwrócić jeden? Lub zwracając wyprowadzone nawet, – miniconco

+0

Z pewnością możesz mieć jedną funkcję, która wykonuje wszystkie trzy kroki, ale celem konwersji 'weak_ptr' na' shared_ptr' jest utrzymywanie obiektu przy życiu podczas pracy z nim; umieszczenie 'shared_ptr' w tymczasowe porażki w tym celu. –

Odpowiedz

5

Nie można skonstruować bezpośrednio swoimi weak_ptr<Saab> z shared_ptr<Car> ponieważ parametr szablonu Car niejawnie musi być wymienialny na Saab w celu podjęcia pracy.

Ale najpierw możesz najpierw przekonwertować swój shared_ptr<Car> na shared_ptr<Saab>, a następnie skonstruować swoją weak_ptr. W moim przykładzie poniżej użyłem do tego celu std::dynamic_pointer_cast.

Oto co wymyśliłem:

#include <iostream> 
#include <vector> 
#include <memory> 

struct Car 
{ 
    virtual void name() = 0; 
}; 

struct Saab : Car 
{ 
    virtual void name() { std::cout << "Saab" << std::endl; } 
}; 

struct Renault : Car 
{ 
    virtual void name() { std::cout << "Renault" << std::endl; } 
}; 

template<typename T> 
std::weak_ptr<T> GetCar(std::vector<std::shared_ptr<Car>> cars) 
{ 
    for (std::vector<std::shared_ptr<Car>>::iterator it = cars.begin(); it != cars.end(); ++it) 
    { 
     auto derived = std::dynamic_pointer_cast<T>(*it); 
     if (derived != nullptr) 
     { 
      std::weak_ptr<T> carPointer(derived); 
      return carPointer; 
     } 
    } 
    return std::weak_ptr<T>(); 
} 

int main() 
{ 
    std::vector<std::shared_ptr<Car>> cars; 
    cars.push_back(std::make_shared<Saab>()); 
    cars.push_back(std::make_shared<Renault>()); 

    auto wp = GetCar<Saab>(cars); 

    auto sp = wp.lock(); 
    if (sp) 
    { 
     sp->name(); 
    } 

    auto wp2 = GetCar<Renault>(cars); 

    auto sp2 = wp2.lock(); 
    if (sp2) 
    { 
     sp2->name(); 
    } 

} 

To wypisuje:

Saab

Renault

Coliru Link: http://coliru.stacked-crooked.com/a/9dbb85b556b83597

+0

Wow! Dokładnie to, czego szukałem! Życzę miłego dnia. – miniconco

Powiązane problemy