https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92849
Bug ID: 92849 Summary: call to 'operator()' incorrectly considered ambiguous, when inherited twice with different type parameters Product: gcc Version: 9.2.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: kholdstare0.0 at gmail dot com Target Milestone: --- Minimal test case: #include <type_traits> template <typename Signature> struct declfunc; template <typename Result, typename... Args> struct declfunc<Result(Args...)> { Result operator() (Args...); }; template <typename... Signatures> struct decloverload : declfunc<Signatures>... { }; using overload_set = decloverload<void(int), void(int, int)>; static_assert(std::is_invocable_v<overload_set, int>); Expected result: compilation succeeds. See the godbolt link below, and try it with clang - clang accepts the code since version 4 Actual result: /opt/compiler-explorer/gcc-9.2.0/include/c++/9.2.0/type_traits:2336:26: error: request for member 'operator()' is ambiguous 2336 | std::declval<_Fn>()(std::declval<_Args>()...) | ~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~ <source>:9:16: note: candidates are: 'Result declfunc<Result(Args ...)>::operator()(Args ...) [with Result = void; Args = {int, int}]' 9 | Result operator() (Args...); | ^~~~~~~~ <source>:9:16: note: 'Result declfunc<Result(Args ...)>::operator()(Args ...) [with Result = void; Args = {int}]' <source>:18:24: error: static assertion failed 18 | static_assert(std::is_invocable_v<overload_set, int>); | ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Compiler returned: 1 Godbolt link with test case as well as '-E' preprocessor output: https://godbolt.org/z/D9nTBr I suspect the ambiguity comes from the fact that two call operators are inherited from the same class (`declfunc` in this case), and the call operators "look the same" - i.e both are `Result operator() (Args...)`. However since `declfunc` is instantiated with different template paramaters, the concrete instances of the call operators are in fact different - Args is `{int}` in one case and `{int, int}` in another. The compiler mentions this in the error message. Perhaps the overload check should descend deeper (using the concrete parameters for `Args...`)