为了防止任何混淆,我非常了解数组和指针之间的区别、衰减到指针的概念以及通过传递数组的概念参考在C++等中
我的问题是具体来说关于编译器从一组函数中选择一个函数所使用的规则overload候选者,当一个重载采用数组引用,而另一个重载采用指针时。
例如,假设我们有:
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;
}
如果我们尝试调用函数模板foo()
如下:
const char arr[2] = "A";
foo(arr);
...那么我的期望是first重载,即采用数组引用的重载,将由编译器选择。
但是,使用 GCC 4.9.2,如果我编译上述代码,则会出现错误:
test.cpp:28:9: error: call of overloaded ‘foo(const char [2])’ is ambiguous
我不清楚为什么编译器在这里将这两个重载视为同样好的候选者,因为第一个重载与类型完全匹配,而第二个重载需要额外的衰减到指针步骤。
现在,我可以通过显式使用来使上述重载工作type_traits
如下:
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;
}
在这种情况下,程序将编译并选择采用数组引用的重载。但是,我不明白为什么这个解决方案是必要的。我想了解为什么当传递的参数很大程度上是一个数组时,编译器将需要衰减到指针的函数视为同样可能的重载候选者作为数组引用。