3

I've wrapped my custom type 'MyType' in a smart pointer:

tr1::shared_ptr<MyType>

and made a vector from it:

vector<shared_ptr<MyType>>

Now I want to std::find an object of type MyType in that vector but can't since the type I'd need would be shared_ptr<MyType>.

Is there an elegant way? Thank you

Update: Why not std::find_if: The usage of std::find is pretty compact. I thought implementing a method or functor for find_if would be a too large overhead.

anhoppe
  • 4,287
  • 3
  • 46
  • 58
  • 1
    you can define operator "==" for shared_ptr, but the only elegant way, not polluting the code is to use find_if – bobah Jan 10 '13 at 07:59
  • The only way is to use find_if. Quote from here (http://en.cppreference.com/w/cpp/memory/shared_ptr/operator_cmp) - `Note that the comparison operators for shared_ptr simply compare pointer values; the actual objects pointed to are not compared.` – borisbn Jan 10 '13 at 08:04
  • The way to do it with the standard library is to use `find_if`. What can't you use that? – Angew is no longer proud of SO Jan 10 '13 at 08:07
  • 1
    Sorry; I’d really like you to explain *why* you don’t want to use `find_if`. Since it’s the correct solution here just throwing that remark out there isn’t helpful. – Konrad Rudolph Jan 10 '13 at 08:14
  • You could also make a heterogeneous `operator==`, between `shared_ptr` and `MyType`. – Benjamin Lindley Jan 10 '13 at 08:17
  • 1
    @BenjaminLindley Heterogeneous comparison operators are a maintenance nightmare, because you also want the left/right symmetry of ordinary comparison, and you have to worry about implicit conversions etc. – TemplateRex Jan 10 '13 at 08:21
  • @rhalbersma: If you expect me to argue in favor of them, you'll be disappointed. – Benjamin Lindley Jan 10 '13 at 08:29
  • @BenjaminLindley Wasn't looking for an argument here, just pointing it out for the poster as well since he was looking for an elegant way. – TemplateRex Jan 10 '13 at 09:02

2 Answers2

12

The idiomatic and elegant way to do what you want is:

std::vector<std::shared_ptr<MyType>> v;

// init v here;

MyType my_value;

// init my_value here;

auto it = std::find_if(v.begin(), v.end(), [&](std::shared_ptr<MyType> const& p) {
    return *p == my_value; // assumes MyType has operator==
});

if (it != v.end()) { /* do what you want with the value found */ }

If you can use std::vector and std:shared_ptr, you are obviously using the STL already. So why not use std::find_if? If you can't use C++11 lambda expressions, you can always use a function object.

BenMorel
  • 34,448
  • 50
  • 182
  • 322
TemplateRex
  • 69,038
  • 19
  • 164
  • 304
  • Cool, thank you, that was helpful. Was not aware that I could use lambda expressions. Sry for the dont-want-find_if comment. I did not want to use find_if because it seemed to me that writing comparison method / functor would not be much more compact then looking up the value by myself. But your solution works and is really what I was looking for. – anhoppe Jan 10 '13 at 08:34
1

To answer just the questions you posted, disregarding your aversion for find_if:

std::vector<std::shared_ptr<MyType>> myVector; 
/* ... */
MyType const& whatIAmlookingFor = /* ... */;
auto ptr = std::find_if(begin(myVector), end(myVector), [&](std::shared_ptr<MyType> const& current)
{
  return *current == whatIAmLookingFor;
});

Now about you not wanting to use find_if "for some reasons" (what reasons might that be?): You are looking for an elegant, STL/boost way to do something, but don't want to use the elegant, STL way to do it? Doesn't sound right.

Arne Mertz
  • 24,171
  • 3
  • 51
  • 90