Try to answer the questions in the code below without compiling.
Now compile each line separately (with either: gcc 11.2 or below / clang 13 or below / MSVC V19.30 or below).
Can you explain what happens?
Which constructor is being called?
#include<queue>
int main() {
std::priority_queue<int> pq1{5, 3}; // what are the values in this queue?
std::priority_queue<double> pq2{5, 3.5}; // and what are the values here?
}
looking at cppref, I don’t see any constructor that fits nicely with this. But I do remember sometime back someone mentioned it in some tweet. It might create verctor (default container) with 2 options:
2 elements
for each {x, y}, it will create x copies of value y.
I’d guess it will be the latter.
It is so very non-intuitive if this is correct
The
template< class InputIt >
priority_queue( InputIt first, InputIt last, const Compare& compare = Compare() );
(priority_queue constructor number 7)
is being called and it need to satisfies LegacyInputIterator.
Now its get tricky…
To satisfy the “LegacyInputIterator” you must satisfy the EqualityComparable requirements:
Now in compile time the “std::priority_queue pq2{5, 3.5};” line 5 is an int and 3.5 is double.
Only in run time, the compiler understands it needs to convert the int into double and because they are not in the same type the result will be always false.
Therefore there is no matching constructor the std::priority_queue can use and we get an error message.
The first line compiles till LWG defect #3522 and treated as two “iterators” (the spec, till defect #3522 expected InputIterator but without stating actual limitations), but then passed to std::vector constructor creating a vector of 5 times 3.
The second line doesn’t compile, since {5, 3.5} are not of the same type, so couldn’t be deduced to the same template parameter type.
Since LWG defect #3522 the first line also fails to compile.
Newer compiler versions would fail the first line, older version would pass it.