gpt4 book ai didi

c++ - 为什么指针衰减优先于推导的模板?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:21:13 26 4
gpt4 key购买 nike

假设我正在编写一个函数来打印字符串的长度:

template <size_t N>
void foo(const char (&s)[N]) {
std::cout << "array, size=" << N-1 << std::endl;
}

foo("hello") // prints array, size=5

现在我想扩展 foo 以支持数组:

void foo(const char* s) {
std::cout << "raw, size=" << strlen(s) << std::endl;
}

但事实证明这打破了我最初的预期用途:

foo("hello") // now prints raw, size=5

为什么?这不需要数组到指针的转换,而模板是完全匹配的吗?有没有办法确保我的数组函数被调用?

最佳答案

这种(符合标准的)歧义的根本原因似乎在于转换成本:重载解析试图最小化将参数转换为相应参数所执行的操作。数组实际上是指向其第一个元素的指针,并装饰有一些编译时类型信息。数组到指针的转换成本不会超过例如保存数组本身的地址,或初始化对它的引用。从这个角度来看,这种歧义似乎是合理的,尽管从概念上讲它是不直观的(并且可能低于标准)。事实上,这个论点适用于所有左值转换,正如下面引述所暗示的那样。另一个例子:

void g() {}

void f(void(*)()) {}
void f(void(&)()) {}

int main() {
f(g); // Ambiguous
}

以下是强制性标准语。不是某些函数模板特化的函数优于那些如果两者在其他方面同样匹配的函数(参见 [over.match.best]/(1.3), (1.6))。在我们的例子中,执行的转换是数组到指针的转换,这是具有精确匹配等级的左值转换(根据 [over.ics.user] 中的表 12)。 [over.ics.rank]/3:

  • Standard conversion sequence S1 is a better conversion sequence than standard conversion sequence S2 if

    • S1 is a proper subsequence of S2 (comparing the conversion sequences in the canonical form defined by 13.3.3.1.1, excluding any Lvalue Transformation; the identity conversion sequence is considered to be a subsequence of any non-identity conversion sequence) or, if not that,

    • the rank of S1 is better than the rank of S2, or S1 and S2 have the same rank and are distinguishable by the rules in the paragraph below, or, if not that,

    • [..]

第一个要点排除了我们的转换(因为它是左值转换)。第二个需要排名差异,但不存在,因为两个转换都具有完全匹配排名; “下面段落中的规则”,即 [over.ics.rank]/4 中的规则,也不涵盖数组到指针的转换。
不管你信不信,两个转换序列中没有一个比另一个更好,因此选择了 char const* - 重载。


可能的解决方法:将第二个重载也定义为函数模板,然后部分排序开始并选择第一个。

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;
}

Demo .

关于c++ - 为什么指针衰减优先于推导的模板?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46157182/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com