用于通过引用传递数组与传递指针的函数参数绑定规则 [英] Function argument binding rules for passing an array by reference vs passing pointer

查看:71
本文介绍了用于通过引用传递数组与传递指针的函数参数绑定规则的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为防止混淆,我非常了解数组和指针之间的区别,衰减指针的概念以及在C ++中通过 reference 传递数组的概念,等等.

我的问题是专门关于编译器用来从一组函数 overload 候选中选择一个函数的规则,当一个重载获取数组引用时,以及另一个重载需要一个指针.

例如,假设我们有:

 模板< class T,std :: size_t N>void foo(const T(& arr)[N]){std :: cout<<数组引用重载!"<<std :: endl;}模板< class T>无效foo(const T * ptr){std :: cout<<指针超载!"<<std :: endl;} 

如果我们尝试如下调用函数模板 foo():

  const char arr [2] ="A";foo(arr); 

...然后,我的期望是编译器会选择 first 重载(采用数组引用的重载).

但是,使用GCC 4.9.2,如果我编译以上代码,则会收到错误消息:

  test.cpp:28:9:错误:重载的"foo(const char [2])"的调用不明确 

对于我来说,目前尚不清楚为什么编译器认为这两个重载都是同样好的候选者,因为第一个重载与类型完全匹配,而第二个重载则需要额外的衰减到指针"步骤.

现在,我可以通过显式使用 type_traits 来实现上述重载,如下所示:

 模板< class T,std :: size_t N>void foo(const T(& arr)[N]){std :: cout<<数组引用重载!"<<std :: endl;}模板< class T>void foo(T ptr,类型名称std :: enable_if< std :: is_pointer< T> :: value> :: type * = 0){std :: cout<<指针超载!"<<std :: endl;} 

在这种情况下,将编译程序并选择采用数组引用的重载.但是,我不明白为什么需要这种解决方案.我想了解为什么当传递的参数是一个数组时,为什么编译器认为一个需要使用衰减指针的函数作为数组引用的可能性也很可能重载.

解决方案

第一个重载与类型完全匹配,而第二个重载则需要额外的衰减到指针"步骤.

因为当检查过载分辨率,即 $ 16.3.3.1.1标准转换顺序[over.ics.scs]表13 —转换

 转化类别排名子条款无需转换身份完全匹配……数组到指针的转换左值变换精确匹配[转换数组]…… 

值得注意的是,无需任何转换"(即第一次过载的情况)的排名也是完全匹配".

To prevent any confusion, I very much understand the difference between arrays and pointers, the concept of decay-to-pointer, and the concept of passing an array by reference in C++, etc.

My question here is specifically about the rules used by the compiler to select a function from a set of function overload candidates, when one overload takes an array reference, and the other overload takes a pointer.

For example, suppose we have:

template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
    std::cout << "Array-reference overload!" << std::endl;
}

template <class T>
void foo(const T* ptr)
{
    std::cout << "Pointer overload!" << std::endl;
}

If we attempt to invoke function template foo() as follows:

const char arr[2] = "A";
foo(arr);

... then my expectation would be that the first overload, the one that takes an array reference, would be selected by the compiler.

However, using GCC 4.9.2, if I compile the above code, I get an error:

test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous

It's unclear to me why both overloads are considered equally good candidates by the compiler here, since the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.

Now, I am able to get the above overload working by explicitly using type_traits as follows:

template <class T, std::size_t N>
void foo(const T (&arr)[N])
{
    std::cout << "Array-reference overload!" << std::endl;
}

template <class T>
void foo(T ptr, typename std::enable_if<std::is_pointer<T>::value>::type* = 0)
{
    std::cout << "Pointer overload!" << std::endl;
}

In this case, the program compiles and the overload that takes an array reference is selected. However, I don't understand why this solution should be necessary. I'd like to understand why the compiler considers a function that requires decay-to-pointer an equally likely overload candidate as the array reference, when the argument passed is very much an array.

解决方案

the first overload matches the type exactly, whereas the second overload requires an extra decay-to-pointer step.

Because when checking the ranking of implicit conversion sequences in overload resolution, the array-to-pointer conversion is considered as an exact match, thus the 2nd overload has the same rank with the 1st one.

From the standard, $16.3.3.1.1 Standard conversion sequences [over.ics.scs] Table 13 — Conversions

Conversion                   Category               Rank         Subclause
No conversions required      Identity               Exact Match
... ...
Array-to-pointer conversion  Lvalue Transformation  Exact Match  [conv.array]
... ...

It's worth noting that the rank of "No conversions required" (i.e. the case for the 1st overload) is "Exact Match" too.

这篇关于用于通过引用传递数组与传递指针的函数参数绑定规则的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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