[Bug c++/92849] New: call to 'operator()' incorrectly considered ambiguous, when inherited twice with different type parameters
kholdstare0.0 at gmail dot com
gcc-bugzilla@gcc.gnu.org
Fri Dec 6 20:09:00 GMT 2019
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...`)
More information about the Gcc-bugs
mailing list