I have two version of the same function using std::any_of
and std::find_if
for checking whether an int
exist in a vector (returned from g.getEdges()
).
However when I repeatedly run the std::any_of
the return value is inconsistent, while std::find_if
is.
Both versions are as follow (g.getEdges()
returns an int
vector, while this->s
is an int
):
bool Search::marked(const int &v) {
return std::any_of(begin(g.getEdges(v)), end(g.getEdges(v)), [this](const int &w) { return w == this->s; });
}
bool Search::marked(const int &v) {
auto it = std::find_if(begin(g.getEdges(v)), end(g.getEdges(v)), [this](const auto &w) { return w == this->s; });
return it != end(g.getEdges(v));
}
In both classes, adj
is the vector being iterated:
class Graph {
public:
Graph() : vertex(0), edges(0) {
adj = std::make_unique<std::vector<std::vector<int>>>(0);
}
const std::vector<int> getEdges(int v) { return (*adj)[v]; }
// ... rest of public
private:
std::shared_ptr<std::vector<std::vector<int>>> adj; // Shared for Search class
}
class Search {
public:
Search(Graph &g_, int s_) : g(g_), s(s_) {}
int count();
bool marked(const int &v);
private:
Graph &g;
int s;
};
The gtest function I used to check the code:
TEST(searchClassTest, HandlesPositiveInput) {
// ... init myGraph ...
Search mySearch(myGraph, 2); // 2 is s!
EXPECT_EQ(mySearch.count(), 2);
EXPECT_EQ(mySearch.marked(1), true);
EXPECT_EQ(mySearch.marked(3), true);
}
Why am I getting inconsistent results?
Link to minimal reproducible example: https://godbolt.org/z/9TnGq3Wbs
The code you presented is totally invalid due to
const std::vector<int> getEdges(int v)
In both implementation of marked
, you call this function multiple times, each time getting a different copy of a vector, then try to compare their iterators:
bool Search::marked(const int &v) {
// begin and end point to two different vectors
auto it = std::find_if(begin(g.getEdges(v)), end(g.getEdges(v)), [this](const auto &w) { return w == this->s; });
// this end points to a third one
return it != end(g.getEdges(v)) ? true : false;
}
The std::any_of
version is broken in the same way. Trying to iterate from one vector to another is Undefined Behavior, so any results you see might as well be random - function might return true
, false
, 7
or "nasal demons, here I come"
.
Simply changing getEdges
to return a reference should fix this.