Consider the following files:
a.cpp
:
#include <queue>
struct Event {
int a;
};
static bool operator<(const Event &a, const Event &b) {
return a.a < b.a;
}
void external_insert(std::priority_queue<Event> &pqu, Event event) {
pqu.push(event);
}
int main() {
// fails
std::priority_queue<Event> pqu;
external_insert(pqu, Event());
// works
// std::priority_queue<Event> pqu;
// pqu.push(Event());
return 0;
}
b.cpp
:
#include <queue>
struct Event {
int a, b;
};
static bool operator<(const Event &a, const Event &b) {
return a.a < b.a;
}
void some_unused_function() {
std::priority_queue<Event> evqu;
evqu.push(Event());
}
Then compile these two files to two executables using:
g++ a.cpp b.cpp -o ab
g++ b.cpp a.cpp -o ba
And then run both under valgrind:
valgrind ./ab
# ... ERROR SUMMARY: 0 errors from 0 contexts ...
valgrind ./ba
# ... ERROR SUMMARY: 2 errors from 2 contexts ...
The exact output from valgrind for the two programs can be found in this gist.
No errors occur when doing either of the following things:
main()
instead of the firstpriority_queue
with vector
, and using push_back
instead of push
I'm inclined to believe this is an issue in the compiler (compiler bug?) where the naming for the template-instantated methods for the two versions of priority_queue
conflict with each other.
Is this a known issue, is this a new bug, or am I missing something?
You have violated the One Definition Rule, so your program has undefined behavior.
To fix it, you can put one or both structs into a namespace to make them unique. If they are not needed outside their own .cpp files, you can put them each into an anonymous namespace.