Andrei Kulagin
Andrei Kulagin

Reputation: 115

How to compare two consecutive elements in c++ list

I need to find two elements with equal fields. They should be consecutive in the same vector. I need to do it with STL method. I've tried using find or find_if but couldn't do it. Can you give me any hint, please?

My code(some parts of it):

class Sound {
    private:
        int notePitch, length;
    public:
        Sound(int notePitch, int length) {
            this->notePitch = notePitch;
            this->length = length;
        }
        int getPitch() {
            std::cout << "Pitch: " << this->notePitch << " length: " << this->length;
            return this->notePitch;
        }
    };

The actual find function:

std::vector<Sound>::iterator iter = masterpiece.begin();
std::vector<Sound>::iterator iterEnd = masterpiece.end();   
std::vector<Sound>::iterator it = find_if(iter, iterEnd, [](auto prev, auto next) -> bool {                 
    return prev.getPitch()  == next.getPitch(); 
});

The error I get is this:

c2678 binary '==' no operator found which takes a left-hand operand of type

Upvotes: 0

Views: 1463

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 311048

The standard algorithm std::find_if does not accept a binary predicate.

You can use the standard algorithm std::adjacent_find with a lambda expression.

The member function getPitch should be declared with the qualifier const. In this case you can use the function for constant objects (for example when an object of the type Sound or a vector of objects Sound is passed to a function that accepts a constant reference)

Here is a demonstrative program

#include <iostream>
#include <vector>
#include <iterator> 
#include <algorithm>

class Sound {
    private:
        int notePitch, length;
    public:
        Sound(int notePitch, int length) {
            this->notePitch = notePitch;
            this->length = length;
        }
        int getPitch() const {
//            std::cout << "Pitch: " << this->notePitch << " length: " << this->length;
            return this->notePitch;
        }
    };

int main( void )
{
    std::vector<Sound> masterpiece = { { 1, 2 }, { 2, 3 }, { 2, 4 }, { 3, 5 } };

    auto it = std::adjacent_find( std::begin( masterpiece ), std::end( masterpiece ),
                                  []( const  Sound &a, const Sound &b )
                                  {
                                    return a.getPitch() == b.getPitch();
                                  } );

    if ( it != std::end( masterpiece ) )
    {
        std::cout << "Two adjacent elements are found at position " 
                  << std::distance( std::begin( masterpiece ), it )
                  << '\n';
    }
    else
    {
        std::cout << "Two adjacent elements are found\n";
    }
}

The program output is

Two adjacent elements are found at position 1

You can the parameters of the lambda expression to write using auto

[]( const auto &a, const auto &b )
{
    return a.getPitch() == b.getPitch();
}

But in any case it is better to declare them as having a const referenced type because in this case neither temporary objects will be created and the lambda expression guarantees that it does not change its arguments.

Upvotes: 1

SolidMercury
SolidMercury

Reputation: 1033

Use adjacent_find in place of find_if. Your code should work.

std::vector<Sound>::iterator it = adjacent_find (iter, iterEnd, [](auto prev, auto next) -> bool {                 
    return prev.getPitch()  == next.getPitch(); 

Upvotes: 1

Related Questions