对重载了ref限定符的成员函数的调用不明确

call of overloaded with ref-qualifiers member function is ambiguous

本文关键字:成员 函数 调用 不明确 重载 ref      更新时间:2023-10-16

当我用G++编译代码时(gcc4.8.1和MinGW4.8.2带有-std=gnu++1y标志),我发现了一个奇怪的行为。本着SSCCE的精神,我隔离了以下片段:

struct C
{
    template< typename X >
    auto
    f(X &&) const &
    { ; }
    template< typename X >
    auto
    f(X &&) &
    { ; }
    template< typename X >
    auto
    f(X &&) &&
    { ; }
};
int main()
{
    int i{};
#if 1
    C{}.f(i);
#endif
#if 1
    C c{};
    c.f(i);
#endif
    return 0;
}

它给出一个错误:

main.cpp: In function 'int main()':
main.cpp:29:10: error: call of overloaded 'f(int&)' is ambiguous
     c.f(i);
          ^
main.cpp:29:10: note: candidates are:
main.cpp:6:5: note: auto C::f(X&&) const & [with X = int&]
     f(X &&) const &
     ^
main.cpp:11:5: note: auto C::f(X&&) & [with X = int&]
     f(X &&) &
     ^
main.cpp:16:5: note: auto C::f(X&&) && [with X = int&]
     f(X &&) &&
     ^

但在#if 1#if 0,或#if 0#if 1的情况下,它可以正常编译。此外,如果我用void替换所有的auto,那么所有的编译也会成功。

是bug,还是我的误导?

g++4.8.2与更简单的(住在coliru)有同样的问题:

struct A {
    auto f() & {}
    auto f() && {}
};
int main() {
    A{}.f();
    A a;
    a.f();
}

尽管程序显然是正确的。这似乎是ref限定符和返回类型推导之间的交互中的一个错误:推断过程可能是在将限定符交给重载解析之前,从隐式对象参数中剥离这些限定符。

我已经将此报告为GCC错误60943。