Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

std::equal not working when using vectors returned by a getter

While learning about how std::equal works, I was writing some test code and ran into this problem:

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

class Foo {

public:
    std::vector<int> vec;

    Foo(std::vector<int> _vec) {
        vec = _vec;
    }

    std::vector<int> get() {
        return vec;
    }

};

int main() {
    
    std::vector<int> x{ 1, 2, 3, 4, 5 };
    std::vector<int> y{ 1, 2, 3, 4, 5 };

    Foo a = Foo(x);
    Foo b = Foo(y);

    std::cout << std::equal(a.vec.begin(), a.vec.end(), b.vec.begin()) << "\n";
    // Outputs: 1

    std::cout << std::equal(a.get().begin(), a.get().end(), b.get().begin()) << "\n";
    // Outputs: 0 <-- why?

    std::cout << (a.get() == b.get());
    // Outputs: 1
}

When I compare two vectors that are returned by the getter function, they are not equal. Why is this?

I understand that if I return by reference in the method std::vector<int>& get, it’ll print that the vectors are equal. However, I might need to use this getter method in a function that takes in a const Foo& argument. However, returning by reference isn’t allowed in a const function (std::vector<int>& get() const is not allowed).

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel


For my practical purpose, I will need to check that two vectors of doubles are equal by checking if each corresponding element’s difference falls within a certain tolerance range. It looks something like this:

bool is_equal(double val1, double val2) {
    return abs(val1 - val2) < 0.0001;
}

Given 2 Foo objects a and b, I want to check if their vectors are equal (vec is private):

std::equal(a.get().begin(), a.get().end(), b.get().begin(), is_equal); // This won't work

For this reason I can’t really use a.get() == b.get() (I would if I could) because rounding inaccuracies might give unwanted results.

Any insight on what’s going on and what I can do? Thanks!

>Solution :

First, return by const reference

const std::vector<int>& get() const {
    return vec;
}

that solves the problem. An alternative would be to have two getters returning the begin and end iterator, instead of returning the vector itself.

Second, the reason for the problem is that your version of the getter copies the vector. so in

std::equal(a.get().begin(), a.get().end(), b.get().begin())

your iterators a.get().begin() and a.get().end() are pointing at two different vectors (both copies of the vector in the class).

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading