1

I have 2 vectors

std::vector<MyObj> v;
std::vector<MyObj2> z;

The objects in the vectors both contain an int that has an ID. I want to see if when looking through v it has a matching id in z

So I thought that I could use `std::find_if and a Lambda.

for (int i=0; i < _z.size(); i++)
{
     MyObj2 _g = _z.at(i);

     auto iter = std::find_if(v.begin(), v.end(), [this](MyObj o) 
     {
        if (o.getID() == _g.getID())
        {
            std::cout << "we have a match" << std::endl;
        }
        else
        {
            std::cout << "we DO NOT have a match" << std::endl;
       }
    });
}

but I am getting an error that I dont understand.

43: Member function 'getID' not viable: 'this' argument has type 'const MyObj2', but function is not marked const

I dont understand what has to be marked const and why?

an I needing something like in my .hpp?:

MyObj2& operator= (const MyObj2&);
MyObj2& operator== (const MyObj2&); 
Jasmine
  • 15,375
  • 10
  • 30
  • 48
  • 3
    Well, the `operator==` should probably return `bool`, and it's normal for it to be `const` anyway. – chris Aug 26 '13 at 04:41
  • 2
    Try marking `getID()` as `const` – Cornstalks Aug 26 '13 at 04:41
  • @chris so change: `MyObj2& operator== (const MyObj2&); ` to `bool operator== (const MyObj2&); `? – Jasmine Aug 26 '13 at 04:49
  • Can you tell me what this `operator=` and `operator==`, etc are called so I can look this up better? – Jasmine Aug 26 '13 at 04:49
  • See [operator overloading](http://stackoverflow.com/questions/4421706/operator-overloading). Anyway, `operator==` should be a free function as well, which will also solve it not being marked `const` if both parameters are const references. – chris Aug 26 '13 at 04:52

2 Answers2

0

You need to declare MyObj2::getID() as const: The compiler says so quite clearly:

struct MyObj2 {
    int getID() const { ... }
    ...
};

It seems, your got a member _g for which this is captured. The _g mentioned before in this example is not captured because the capture clause explicitly restricts the capture to this. If you used the _g from the scope, getID() wouldn't need to be const.

Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
0

From cppreference about find_if:

UnaryPredicate must meet the requirements of Predicate.

wich liks to the concept of Predicate:

The Predicate concept describes a function object that takes a single iterator argument that is dereferenced and used to return a value testable as a bool.
In other words, if an algorithm takes a Predicate pred and an iterator first, it should be able to test the iterator using the predicate via a construct like if (pred(*first)) {...}.
The function object pred shall not apply any non-constant function through the dereferenced iterator. This function object may be a pointer to function or an object of a type with an appropriate function call operator.

There are two requirements stated in that text:

  1. Your predicate (i.e. the lambda) has to return something convertible to bool. Some output to cout is not sufficient.
  2. Your predicate is not allowed to call nonconst functions on the argument (i.e. the MyObj)

However, your code shows lots of compile errors but nothing that relates to the error you stated in your question. This is because you did not provide an SSCCE:

  • You did not capture _g in the lambda expression
  • You get compile errors if the predicate does not return something convertible to bool (see requirements for the predicate above)
  • you mismatched z and _z

I do not get the errors you described, because in your example code you copy the values from the vectors instead of taking a const reference. Copying is fine of course, and you can apply any non-const functions to those copies. I have a compileable mini-example of your code here: http://ideone.com/o8tPED

However, this is not how it should be implemented:

  • You should take references instead of copies of the vector elements (I am almost sure you do that in reality)
  • To avoid the error you reported, you will then have to declare both getID functions const. You should do that regardless of the usage in the algorithm, because functions that don't change the object should always say so.
Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • This is a great answer. I read it and looked at the docs and I clearly see my mistake! I forgot about needing to return a bool and using `[&]` as the return in the lambda. – Jasmine Aug 26 '13 at 15:09
  • @Jason Glad I could help (feel free to accept the answer if if fixed your problem). However, I strongly suggest you copy&paste real code next time (see the SSCCE link). It makes things much easier for anyone wanting to help :-) – Arne Mertz Aug 26 '13 at 15:14
  • I agree, I was trying to not make everyone read all the code and that is a mistake. I'll accept the answer. I realize I have one source on confusion to look up. I thought in lambda `[]`, `[=]`, `[this]` are all the same and what is confusing me is I think of `[&]` as returning `by reference` which to me seems to the the same thing as `const` in this case so the `getID()` doesn't need to be marked as const (and it is an inline header function, actually) – Jasmine Aug 26 '13 at 15:29
  • and as a matter of clarity, if I have `getter` functions that just simply return a member variable, I should mark those as `const` just to be safe/sure as they would never change the return value? – Jasmine Aug 26 '13 at 15:32
  • `[]`, `[=]` and `[this]` are completely different captures. I used `[&]` for brevity and in order to avoid another unnecessary copy of `_g` – Arne Mertz Aug 26 '13 at 15:50
  • To my Bjarne book I go. No substitute for reading and studying. – Jasmine Aug 26 '13 at 15:57