https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85965
Bug ID: 85965 Summary: G++ gives cryptic error instead of incomplete type Product: gcc Version: 8.1.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: psmith at gnu dot org Target Milestone: --- Compiling code with GCC 8.1 / binutils 2.30 (built locally on GNU/Linux amd64) which previously compiled and worked OK with GCC 6.2 and 7.3. I received a very cryptic error that had me running around reworking class implementations for quite a while before I realized the problem: I had an incomplete type. I don't know if there's anything G++ could do better here, but FYI I had this code: class Bar { public: struct Less { bool operator()(const Bar& lhs, const Bar& rhs) const; bool operator()(const Bar* lhs, const Bar* rhs) const; }; }; class Biz; #include <set> class Foo { std::set<const Biz*, Bar::Less> _map; }; It's not immediately clear that the incomplete Biz class is a problem, especially in my code which is significantly more complex and crosses multiple header files, and G++ doesn't give a very helpful (to me) error: $ g++ -o set.o -c set.cpp In file included from x86_64-generic-linux-gnu/include/c++/8.1.0/set:60, from set.cpp:13: x86_64-generic-linux-gnu/include/c++/8.1.0/bits/stl_tree.h: In instantiation of 'class std::_Rb_tree<const Biz*, const Biz*, std::_Identity<const Biz*>, Bar::Less, std::allocator<const Biz*> >': x86_64-generic-linux-gnu/include/c++/8.1.0/bits/stl_set.h:133:17: required from 'class std::set<const Biz*, Bar::Less>' set.cpp:17:37: required from here x86_64-generic-linux-gnu/include/c++/8.1.0/bits/stl_tree.h:452:21: error: static assertion failed: comparison object must be invocable with two arguments of key type static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{}, ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If I had included the complete type for class Biz, the compiler would have seen that Biz is a subclass of Bar and it would have been fine; adding in the header file fixed my problem: class Bar { public: struct Less { bool operator()(const Bar& lhs, const Bar& rhs) const; bool operator()(const Bar* lhs, const Bar* rhs) const; }; }; class Biz : public Bar {} #include <set> class Foo { std::set<const Biz*, Bar::Less> _map; };