【问题标题】:C++ Overload resolution ambiguous - GCCC++ 重载解析模棱两可 - GCC
【发布时间】:2014-01-21 19:13:20
【问题描述】:

我试图理解,为什么 GCC 在下面的代码中选择 f(char, A<C, 5> &var) 进行重载解析:

template <class C, int N> struct A { };
template <class C> struct A<C, 8> { static_assert(sizeof(C) > 8, "Assertion in A<C,8>"); };
template <class C> struct A<C, 5> { static_assert(sizeof(C) < 8, "Assertion in A<C,5>"); operator A<C,8>&(); };

template <class C> void f(double, A<C,8> &var);
template <class C> void f(char, A<C,5> &var);

int main(void)
{
    A<int, 5> a;
    f(4., a);
}

有两个重载可用:

template <class C> void f(double, A<C,8> &var);

4. 完全匹配 double(不需要隐式转换),但第二个参数需要用户定义的转换。所以这个重载:exact match & user-define conversion

下一个重载,由 GCC 匹配:

template <class C> void f(char, A<C,5> &var);

4. 需要隐式转换为 char 但与 A&lt;C,5&gt; 完全匹配。 GCC 有什么理由选择这个重载而不是前一个?

有人可以从标准第 13 节中找到有关此特定案例的证据吗?任何帮助或评论表示赞赏。谢谢!

【问题讨论】:

    标签: c++ gcc c++11 standards overload-resolution


    【解决方案1】:

    推论不能成功

    template <class C> void f(double, A<C,8> &var);
    

    A&lt;int, 5&gt; 类型的参数。 IE。没有可能的类型C 可以使A&lt;C,8&gt; 匹配参数类型A&lt;int,5&gt;。可以转换不考虑扣除。

    参见 [temp.deduct.call]/4。由于可以通过转换构造函数和转换函数进行转换,因此不可能考虑(所有)转换进行类型推导。这也可能导致歧义。

    【讨论】:

    • 您可以通过删除第二个重载来看到这一点。 clang++ 输出:候选模板被忽略:无法将 8 与 5 匹配
    • 你是对的,gcc 在第二个重载被注释掉时也会出错。
    • 感谢您的回复。所以 clang 和 gcc 不关心用户定义的转换。那是operator A&lt;C,8&gt;&amp;();?
    • @User Well 类型推导不考虑可能的转换,operator A&lt;C,8&gt;&amp; () 是一种不考虑类型推导的此类转换。如果您显式传递模板参数(通常不推荐),您将得到预期的歧义:f&lt;int&gt;(4., a); is ambiguous
    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 2015-10-12
    • 2015-01-12
    • 1970-01-01
    • 2012-12-08
    • 1970-01-01
    • 2013-11-18
    • 2016-01-03
    相关资源
    最近更新 更多