2016-07-07 16 views
5

この問題を回避するには問題があります。 私はこのベクトルを持っているとしましょう。shared_ptrからweak_ptr多型への変換

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

車は抽象クラスです。 私は以下のことをするために、異なるタイプの弱いポインタを返すことができるようにしたい。

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>(); 
    } 

Carから継承するクラスでこの関数を使用しようとすると、次のエラーが発生します。 Error C2440 'initializing': cannot convert from 'std::shared_ptr<Car>' to 'std::weak_ptr<Saab>' 尋ねられたら、有効な車が存在しない可能性があります。 boost :: optionalを使ってみましたが、多態性は扱えません。私はこれを動作させることができない場合、生のポインタで行くかもしれません。

+1

'shared_ptr'と' weak_ptr'が指す型は同じでなければなりません。私はこれを3段階で行います: 'weak_ptr 'を返し、それを 'shared_ptr 'に変換し、 'T *'に変換します。 –

+0

素早く答えてくれてありがとう@MarkRansom Mmm。これはライブラリのユーザ機能のためのものなので、私はむしろそれをより多くの仕事を使用するかもしれない開発者を与えてはいけません。そう言わなければならない、悪い。私は1つを返すことができるので、あなたはrawポインタだけで作業することをお勧めしますか?または、偶数を返すこともできます。 – miniconco

+0

3つのステップすべてを実行する単一の関数を使用することはできますが、 'weak_ptr'を' shared_ptr'に変換する目的は、オブジェクトの操作中にそのオブジェクトを存続させることです。 'shared_ptr'を一時的なものにすることは、その目的に反します。 –

答えて

5

テンプレートパラメータCarが暗黙的に機能するためにはSaabに変換可能でなければならないので、あなたがshared_ptr<Car>から直接weak_ptr<Saab>を構築することはできません。

最初にshared_ptr<Car>shared_ptr<Saab>に変換してから、weak_ptrを後で作成することができます。私の例では、std::dynamic_pointer_castを使っていました。ここで

は私が思い付いたものです:

#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(); 
    } 

} 

それが出て出力します。

サーブ

ルノー

Coliruリンク:http://coliru.stacked-crooked.com/a/9dbb85b556b83597

+0

うわー!まさに私が探していたもの!良い一日を過ごしてください。 – miniconco

関連する問題