質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
86.02%
Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

Q&A

解決済

shared_ptrを格納したvectorコンテナでのエラー

asdfghjkl_12345
asdfghjkl_12345

総合スコア24

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

2回答

0グッド

0クリップ

359閲覧

投稿2022/08/30 05:40

編集2022/08/30 05:41

初学者のため、初歩的なミスやわかりづらいところ等がありましたらすみません。

Microsoft Visual Studio Community 2022 (64 ビット) - Current
Version 17.3.2
において、C++でプログラムを書いているのですが、メモリリークが気になり、shared_ptrを導入してみたところ、
以前はコンパイルが通り、プログラムも動作していたところが、コンパイルエラーになりました。

該当のソースコード

※型、変数の名前は変更しています

class Base{...}; //基底クラス

class Derived1 : public Base{...}; //派生クラス1

class Derived2 : public Base{...}; //派生クラス2

//派生クラスを基底クラスポインタで格納するvectorコンテナ
//std::vector<Base*>からstd::vector<std::shared_ptr<Base>>に変更
//要素はいくつか入っている
std::vector<std::shared_ptr<Base>> Container = {...};

//thisはDerived1やDerived2などの派生クラスポインタ

//vectorコンテナを探して、thisが無ければ、vectorコンテナに格納する
std::vector<std::shared_ptr<Base>>::iterator iter =
std::find(Container.begin(),Container.end().this);

if (iter == Container.end())
{
Container.emplace_back(this);
}

発生している問題・エラーメッセージ

重大度レベル コード 説明 プロジェクト ファイル 行 抑制状態
エラー C2678 二項演算子 '==': 型 'std::shared_ptr<Base>' の左オペランドを扱う演算子が見つかりません (または変換できません) (新しい動作; ヘルプを参照)。
メッセージ 'bool std::operator ==(std::thread::id,std::thread::id) noexcept' [引数依存の照合を使用して検出] の可能性があります
メッセージ または 'bool operator ==(const GUID &,const GUID &)' [引数依存の照合を使用して検出] の可能性があります
メッセージ または 'ビルトイン C++ 演算子==(_Ty, _Ty)'
メッセージ 引数リスト '(std::shared_ptr<Base>, const _Ty)' を一致させようとしているとき
メッセージ コンパイル対象の関数 テンプレート インスタンス化 '_InIt std::_Find_unchecked<std::shared_ptr<Base>,_Ty>(_InIt,const _InIt,const _Ty &)' のリファレンスを確認してください
メッセージ コンパイル対象の関数 テンプレート インスタンス化 '_InIt std::find<std::_Vector_iterator<std::_Vector_val<std::_Simple_types<_Ty>>>,Derived1
>(_InIt,const _InIt,Derived1 *const &)' のリファレンスを確認してください

実現したいこと

thisはshared_ptrではないから比較できない、というのはなんとなくわかるのですが、thisとshared_ptrから出した何かを比較するのか(.get()をstd::find()のどこかに入れられる、等)、あるいはthis等のクラスインスタンス自身をshared_ptrと比較できる形にできるのか等、dynamic_castやstd::dynamic_pointer_castは適用できないようですが、わかりません。
他の部分や基底、派生クラスが包含するクラスにもshared_ptrは使用していますが、現在ではエラー箇所はこの箇所のみとなっています。エラー箇所ははっきりしないのですが、同様のstd::find()使用の2箇所なので、おそらくこのstd::find()がエラー箇所だと思うのですが、生ポインタではなくshared_ptrをvectorコンテナに格納して、プログラムが動作するようにしたいです。

よろしくお願いします。

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

気になる質問をクリップする

クリップした質問は、後からいつでもマイページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答2

0

すみません。

thisポインタをshared_ptrにする方法があるようですね。
https://teratail.com/questions/50979

現在回答いただいたものと合わせてとりあえず試してみてからまた書きます

投稿2022/08/30 05:59

編集2022/08/30 06:25
asdfghjkl_12345

総合スコア24

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

ベストアンサー

std::find_if(Container.begin(),Container.end(). [](auto s_ptr) { return s_ptr.get() == this;});

ではダメですか?

投稿2022/08/30 05:56

episteme

総合スコア16005

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

fana

2022/08/30 07:00

突然横からの質問となり,恐縮ですが, この場合 auto s_ptr の実際の型って何になるのでしょうか?(っていうのが何から定まるのでしょう?) shared_ptr<Base> でしょうか? (shared_ptr<Base>& や const shared_ptr<Base> & を意図するなら "auto &" とか "const auto &" とか書く?)
episteme

2022/08/30 07:15

shared_ptr<Base> のハズです。
fana

2022/08/30 08:54

ラムダ式の内部で引数の use_count() を見たり,引数に代入を試みたりした感じだと,shared_ptr<Base> ですね. auto のところを ・auto & にすれば shared_ptr<Base>& ・const auto & にすれば const shared_ptr<Base> & ・auto & にして find_if の引数を cbegin(),cend() にすれば const shared_ptr<Base> & と.
asdfghjkl_12345

2022/09/03 11:47

回答ありがとうございます。 返信が遅くなってすみません。 ラムダ式はあまりよくわからないのですが、教えていただいた方法を試してみたところ、 std::vector<std::shared_ptr<Base>>::iterator iter = std::find_if( Container.begin(), Container.end(), [&](auto& s_ptr) { return s_ptr.get() == derived1.get(); } ); if (iter == Container.end()) { Container.emplace_back(derived1); } でいけました。 それと、std::enable_shared_from_this<>も試してみたんですが、後だしの情報で申し訳ないのですが、 クラスの継承のところが、本来は class Base{...}; //基底クラス class Derived1 : public Base{...}; //派生クラス1 class Derived2 : public Derived1{...}; //派生クラス2 でした。 それで、Class Derived1:public std::enable_shared_from_this<Derived1>にして、 Class Derived2:public std::enable_shared_from_this<Derived2>とすると、 Derived2にshared_from_this()があいまいですと出て、これがどうやって解決するのかわからず。 そもそもthisをshared_ptrに変換したかった理由が、クラスインスタンスポインタが、自身の関数から自身(this)を静的コンテナを検索して、無ければ自身(this)を格納したかったからで、構造から変更して関数の外で自身をshared_ptrで格納すればよいと気づき、その場合はstd::enable_shared_from_this<>は必要ないかもと。 しかしshared_ptrはポインタがポインタを内包しているのか、同型、派生クラスのshared_ptrから代入などしたら参照カウンタはどうなるんだろうとか、まだ挙動や構造がつかめませんでした。 なので、まだまだ自身の勉強不足で、shared_ptrについては複雑なところへの採用は保留にしようかと思いました。

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
86.02%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問

同じタグがついた質問を見る

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。