为什么这里的模糊? [英] Why is this ambiguity here?

查看:146
本文介绍了为什么这里的模糊?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑我有以下最小代码:

  #include< boost / type_traits.hpp> 

template< typename ptr_t>
struct TData
{
typedef typename boost :: remove_extent< ptr_t> :: type value_type;
ptr_t data;

value_type& operator [](size_t id){return data [id]; }
operator ptr_t& (){return data; }
};

int main(int argc,char ** argv)
{
TData< float [100] [100] t;
t [1] [1] = 5;
return 0;
}

GNU C ++给我的错误:

  test.cpp:在函数'int main(int,char **)'中:
test.cpp:16:error:ISO C ++说是不明确的,即使第一个的最坏转换好于第二个的最坏转换:
test.cpp:9:note:candidate 1:typename boost :: remove_extent< ptr_t> :: type& TData< ptr_t> :: operator [](size_t)[with ptr_t = float [100] [100]]
test.cpp:16:note:candidate 2:operator [] ,int)< built-in>

我的问题是:




  1. 为什么GNU C ++给出错误,但是Intel C ++编译器不是?

  2. ] 到以下导致编译没有错误?


    value_type& operator [](int id){return data [id]; }



    $ b










    我可以看到两个转换路径:


    1. int size_t 和(2) operator [](size_t)

    2. (1) operator ptr_t&(),(2) int size_t 和(3)内置 operator [](size_t)


    解决方案

    这是很直接的。对于 t [1] ,重载解析有这些候选人:



    候选1(内置: 13)(T是某种任意对象类型):




    • 参数列表: ptrdiff_t)



    候选人2(您的运营商) b
    $ b


    • 参数列表:(TData< float [100] [100]& something,uns unsigned)



    参数列表由 13.3.1.2/6


    用于重载解析的候选函数集是成员候选,非成员候选和内置候选的联合。参数列表包含运算符的所有操作数。





    • 参数列表:(TData< float [100] [100]> ;, int)



    第一个参数完全匹配候选2的第一个参数。但是它需要用户为Candidate 1的第一个参数定义转换。因此对于第一个参数,第二个候选者获胜。



    您还可以看到第二个位置的结果取决于。让我们做一些假设,看看我们得到了什么:


    1. ptrdiff_t $ c> int :第一个候选者获胜,因为它有一个完全匹配,而第二个候选者需要一个完整的转换。

    2. ptrdiff_t long :两个候选都不会获胜,转换。

    现在, 13.3.3 / 1


    令ICSi(F)表示将列表中的第i个参数转换为可行函数F的第i个参数的类型的隐式转换序列。



    可行函数F1被定义为比另一个可行函数F2更好的函数,如果对于所有参数i,ICSi(F1)不是比ICSi F2),然后...对于一些参数j,ICSj(F1)是比ICSj(F2)更好的转换序列,或者如果不是... ...


    对于我们的第一个假设,我们没有得到一个整体的赢家,因为候选2赢得第一个参数,候选1赢得第二个参数。我称之为交叉。对于我们的第二个假设,候选2胜过整体,因为两个参数都没有更差的转换,但第一个参数有一个更好的转换。



    对于第一个假设,第二个参数中的整数转换(int到无符号)比其他参数的用户定义转换候选者在第一个参数。在十字交叉,规则是粗糙的。






    最后一点可能仍然让你困惑,因为所有的事情,让我们举一个例子

      void f(int,int){} 
    void f(long,char){}

    int main(){f(0,'a'); }

    这会给你一个混乱的GCC警告(我记得, ),因为 0 转换为 long 'a'到 int - 但你却有歧义,因为你处于交叉状态。


    Consider I have the following minimal code:

    #include <boost/type_traits.hpp>
    
    template<typename ptr_t>
    struct TData
    {
        typedef typename boost::remove_extent<ptr_t>::type value_type;
        ptr_t data;
    
        value_type & operator [] ( size_t id ) { return data[id]; }
        operator ptr_t & () { return data; }
    };
    
    int main( int argc, char ** argv )
    {
        TData<float[100][100]> t;   
        t[1][1] = 5;
        return 0;
    }
    

    GNU C++ gives me the error:

    test.cpp: In function 'int main(int, char**)':
    test.cpp:16: error: ISO C++ says that these are ambiguous, even though the worst conversion for the first is better than the worst conversion for second:
    test.cpp:9: note: candidate 1: typename boost::remove_extent<ptr_t>::type& TData<ptr_t>::operator[](size_t) [with ptr_t = float [100][100]]
    test.cpp:16: note: candidate 2: operator[](float (*)[100], int) <built-in>
    

    My questions are:

    1. Why GNU C++ gives the error, but Intel C++ compiler is not?
    2. Why changing operator[] to the following leads to compiling without errors?

      value_type & operator [] ( int id ) { return data[id]; }

    Links to the C++ Standard are appreciated.


    As I can see here are two conversion paths:

    1. (1)int to size_t and (2)operator[](size_t).
    2. (1)operator ptr_t&(), (2)int to size_t and (3)build-in operator[](size_t).

    解决方案

    It's actually quite straight forward. For t[1], overload resolution has these candidates:

    Candidate 1 (builtin: 13.6/13) (T being some arbitrary object type):

    • Parameter list: (T*, ptrdiff_t)

    Candidate 2 (your operator)

    • Parameter list: (TData<float[100][100]>&, something unsigned)

    The argument list is given by 13.3.1.2/6:

    The set of candidate functions for overload resolution is the union of the member candidates, the non-member candidates, and the built-in candidates. The argument list contains all of the operands of the operator.

    • Argument list: (TData<float[100][100]>, int)

    You see that the first argument matches the first parameter of Candidate 2 exactly. But it needs a user defined conversion for the first parameter of Candidate 1. So for the first parameter, the second candidate wins.

    You also see that the outcome of the second position depends. Let's make some assumptions and see what we get:

    1. ptrdiff_t is int: The first candidate wins, because it has an exact match, while the second candidate requires an integral conversion.
    2. ptrdiff_t is long: Neither candidate wins, because both require an integral conversion.

    Now, 13.3.3/1 says

    Let ICSi(F) denote the implicit conversion sequence that converts the i-th argument in the list to the type of the i-th parameter of viable function F.

    A viable function F1 is defined to be a better function than another viable function F2 if for all arguments i, ICSi(F1) is not a worse conversion sequence than ICSi(F2), and then ... for some argument j, ICSj(F1) is a better conversion sequence than ICSj(F2), or, if not that ...

    For our first assumption, we don't get an overall winner, because Candidate 2 wins for the first parameter, and Candidate 1 wins for the second parameter. I call it the criss-cross. For our second assumption, the Candidate 2 wins overall, because neither parameter had a worse conversion, but the first parameter had a better conversion.

    For the first assumption, it does not matter that the integral conversion (int to unsigned) in the second parameter is less of an evil than the user defined conversion of the other candidate in the first parameter. In the criss-cross, rules are crude.


    That last point might still confuse you, because of all the fuss around, so let's make an example

    void f(int, int) { }
    void f(long, char) { }
    
    int main() { f(0, 'a'); }
    

    This gives you the same confusing GCC warning (which, I remember, was actually confusing the hell out of me when I first received it some years ago), because 0 converts to long worse than 'a' to int - yet you get an ambiguity, because you are in a criss-cross situation.

    这篇关于为什么这里的模糊?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆