The following testcase extracted from Cython is no longer accepted with G++7: > g++-7 -c t.C In file included from /usr/include/c++/7/bits/stl_algobase.h:71:0, from /usr/include/c++/7/algorithm:61, from t.C:1: /usr/include/c++/7/bits/predefined_ops.h: In instantiation of ‘struct __gnu_cxx::__ops::_Iter_comp_iter<bool(int, int)>’: /usr/include/c++/7/bits/stl_heap.h:394:51: required from ‘void std::make_heap(_RAIter, _RAIter, _Compare) [with _RAIter = __gnu_cxx::__normal_iterator<int*, std::vector<int> >; _Compare = bool(int, int)]’ t.C:8:34: required from here /usr/include/c++/7/bits/predefined_ops.h:132:16: error: field ‘__gnu_cxx::__ops::_Iter_comp_iter<bool(int, int)>::_M_comp’ invalidly declared function type _Compare _M_comp; ^~~~~~~ while it is just fine with g++6: > g++-6 -c t.C >
clang++ errors the same way btw, so maybe G++6 (bogously) did not instantiate this type.
#include <algorithm> #include <vector> bool greater(int, int); int main() { std::vector<int> v; std::make_heap<std::vector<int>::iterator, bool (int, int)> (v.begin(), v.end(), greater); }
https://github.com/cython/cython/issues/1632
I think the testcase is invalid. std::make_heap is declared like so: template<class RandomAccessIterator> void make_heap(RandomAccessIterator first, RandomAccessIterator last); template<class RandomAccessIterator, class Compare> void make_heap(RandomAccessIterator first, RandomAccessIterator last, Compare comp); The explicit instantiation matches the second overload, then argument substitition creates the function: void make_heap(vector<int>::iterator first, vector<int>::iterator last, bool(comp)(int, int)); You can't pass functions by value so the third argument decays to: void make_heap(vector<int>::iterator first, vector<int>::iterator last, bool(*comp)(int, int)); However, this means the type of the function parameter comp is no longer of type Compare, and so if the implementation tries to use that type it will fail, e.g. GCC 7 does something like: struct wrapper { Compare cmp; } wrapped_comp = { comp }; And libc++ does something like: Compare& ref = comp; Both fail, because Compare is a function type, but comp is a pointer to function. The test should use: std::make_heap<std::vector<int>::iterator, bool(*)(int, int)> That is the actual type that is deduced for the greater argument.
Re-opening because we can make it work fairly easily, by using the decayed type instead of the original Compare type, i.e. struct wrapper { __decltype(comp) cmp; } wrapped_comp = { comp };
Author: redi Date: Thu Mar 16 14:32:07 2017 New Revision: 246197 URL: https://gcc.gnu.org/viewcvs?rev=246197&root=gcc&view=rev Log: PR libstdc++/80064 make heap algorithms work with function types PR libstdc++/80064 * include/bits/stl_heap.h (__is_heap, push_heap, __adjust_heap) (pop_heap, make_heap, sort_heap, is_heap_until, is_heap): Cope with invalid instantiations using function types for _Compare argument. * testsuite/25_algorithms/make_heap/80064.cc: New test. Added: trunk/libstdc++-v3/testsuite/25_algorithms/make_heap/80064.cc Modified: trunk/libstdc++-v3/ChangeLog trunk/libstdc++-v3/include/bits/stl_heap.h
Fixed. We might consider a static_assert for gcc8 to reject this code with a user-friendly diagnostic, but for now let's accept what used to work.