通过引用限定符成员函数的重载调用是不明确的。

7

我发现一个奇怪的行为,当使用G++(gcc 4.8.1,MinGW 4.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的情况下,编译可以正常进行。如果将所有的auto替换为void,则所有内容也可以成功编译。

这是一个Bug还是我的误解?


请纠正我如果我错了,但是这看起来像完美的转发机制(C++11中右值引用的推导规则)正在困扰你。https://dev59.com/m3A65IYBdhLWcg3w4C2j。基本上,在`template <typename T> void foo(T&& t)中,T&&`实际上充当“通用”引用而不是右值引用。实际的推导规则对我来说非常令人困惑。 - IdeaHat
另一个链接:http://isocpp.org/blog/2012/11/universal-references-in-c11-scott-meyers - IdeaHat
1
@MadScienceDreams 这并不重要,因为如果我们将所有 X && 的出现替换为 X const &,那么一切都保持不变。 - Tomilov Anatoliy
6
这几乎肯定是在g ++中ref限定符与返回类型推断之间交互时的一个错误。在Coliru上,clang(post 3.4版本)编译程序时没有投诉即使成员非模板化,Coliru上的g ++(4.8.2)也拒绝编译它。如果有人能够在4.9上运行它,那就太好了。 - Casey
@MadScienceDreams 这段代码与其原型 bitbucket.org/insituc/variant 相比相当简单。 - Tomilov Anatoliy
1个回答

4

g++ 4.8.2在处理更简单的代码(Live at coliru)时也存在相同的问题:

struct A {
    auto f() & {}
    auto f() && {}
};

int main() {
    A{}.f();
    A a;
    a.f();
}

尽管程序显然是正确的,但似乎存在ref-qualifier和返回类型推断之间交互中的错误:推断过程可能会在将隐式对象参数移交给重载决策之前剥离限定符。我已将此报告为GCC bug 60943

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接