重载解析中的歧义:指针衰减与模板推导
在 C 中,当重载函数可用时,确定调用哪个函数可以模棱两可。其中一种情况涉及指针衰减优先于推导模板。
歧义的根源
考虑一个打印字符串长度的函数:
template <size_t N> void foo(const char (&s)[N]) { std::cout << "array, size=" << N - 1 << std::endl; } foo("hello") // prints array, size=5
为了支持非数组,额外的重载是添加:
void foo(const char* s) { std::cout << "raw, size=" << strlen(s) << std::endl; }
意外的是,第一个重载不再被调用:
foo("hello") // now prints raw, size=5
指针衰减与模板推导
歧义之所以出现这种情况,是因为数组本质上是指向其第一个元素的指针。当将数组作为参数传递时,指针衰减会自动将数组转换为指针。但是,模板推导将导致与第一个重载完全匹配。
根据 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; }
By指定类型约束,编译器可以推断出第一个重载应该用于数组,而第二个重载则处理非数组。
总之,虽然指针衰减提供了访问第一个元素的快捷方式数组,当涉及模板时,它可能会导致重载决策中出现意外的歧义。仔细考虑函数重载和深思熟虑地使用类型约束是避免此类陷阱的关键。
以上是C 重载解析中指针衰减何时会覆盖模板推导?的详细内容。更多信息请关注PHP中文网其他相关文章!