指针衰减与推导模板:解开优先级难题
在 C 领域,函数重载和模板推导之间的相互作用可以有时会导致意想不到的结果。当函数被重载以处理数组和原始指针时,就会出现一个典型的例子。考虑以下代码:
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N - 1 << std::endl; } void foo(const char *s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
最初设计用于打印数组的长度,此函数已扩展为支持非数组。然而,这个扩展导致了一个令人费解的歧义:
foo("hello") // now prints raw, size=5
为什么选择“原始”重载而不是预期的“数组”版本,尽管后者更精确地匹配参数?答案在于一个微妙的概念,称为指针衰减。
指针衰减是从数组到其相应指针的隐式转换。在这种情况下,数组“hello”会默默地转换为指向其第一个元素的 const char * 指针。因此,处理指针的重载优先。
此行为源于 C 中的转换成本。评估重载以最小化将参数转换为形参的成本。在这种情况下,数组到指针的转换比数组到函数参数的转换成本更低。
要解决此问题,也可以将第二个重载定义为模板:
template <typename T> auto foo(T s) -> std::enable_if_t<std::is_convertible<T, char const *>{}> { std::cout << "raw, size=" << std::strlen(s) << std::endl; }
这种方法确保模板版本是首选,因为它消除了指针衰减转换。
总之,指针衰减优先于推导模板是重载解决方案中成本最小化原则的结果。为了避免歧义,在重载函数时考虑隐式转换和重载类型至关重要。
以上是为什么在 C 重载解析中指针衰减优先于推导模板?的详细内容。更多信息请关注PHP中文网其他相关文章!