gpt4 book ai didi

c++ - 为什么这个函数在给定右值参数的情况下返回一个左值引用?

转载 作者:IT老高 更新时间:2023-10-28 23:01:41 24 4
gpt4 key购买 nike

min 的以下定义功能

template <typename T, typename U>
constexpr auto
min(T&& t, U&& u) -> decltype(t < u ? t : u)
{
return t < u ? t : u;
}

有一个问题:看起来写是完全合法的

min(10, 20) = 0;

这已经用 Clang 3.5 和 g++ 4.9 进行了测试。

解决方案很简单,只需使用 std::forward恢复参数的“右值”,即修改正文和 decltype

t < u ? std::forward<T>(t) : std::forward<U>(u)

但是,我无法解释为什么第一个定义不会产生错误。


鉴于我对转发和通用引用的理解,tu将它们的参数类型推断为 int&&当传递整数文字时。但是,在 min 的正文中,参数有名称,所以它们是左值。现在,really complicated rules for the conditional operator come into play ,但我认为相关的行是:

  • Both E2 [and] E3 are glvalues of the same type. In this case, the result has the same type and value category.

因此返回类型为 operator?:应该是 int&&同样,不应该吗?但是,(据我所知)Clang 和 g++ 都有 min(int&&, int&&)返回一个左值引用 int& ,从而允许我分配结果。

显然,我的理解存在差距,但我不确定我到底错过了什么。谁能给我解释一下这里到底发生了什么?


编辑:

正如 Niall 正确指出的那样,这里的问题不在于条件运算符(它按预期返回 int&& 类型的左值),而在于 decltype . decltype 的规则说

if the value category of expression is lvalue, then the decltype specifies T&

所以函数的返回值变成了int&& & ,根据 C++11 的引用折叠规则变成普通的 int& (与我预期的 int&& 相反)。

但是如果我们使用 std::forward , 我们把 operator?: 的第二个和第三个参数(返回)到右值 - 具体来说,xvalues。由于 xvalues 仍然是 glvalues(你在后面跟上吗?),同样的条件运算符规则适用,我们得到相同类型和值类别的结果:即 int&&这是一个 xvalue。

现在,当函数返回时,它会触发不同的 decltype规则:

if the value category of expression is xvalue, then the decltype specifies T&&

这一次,引用折叠给了我们int&& && = int&&而且,更重要的是,该函数返回一个 xvalue。这使得分配给返回值是非法的,正如我们所希望的那样。

最佳答案

问题可能与 decltype() 规则有关。

这是暗示的;如果删除了尾随返回类型

template <typename T, typename U>
constexpr auto
min(T&& t, U&& u)
{
return t < u ? t : u;
}

并且允许编译器推断它,return type is int .

decltype的使用

decltype ( expression )
...
if the value category of expression is lvalue, then the decltype specifies T&

取自 cppreference .

由于涉及 tu 的表达式是左值(它们是左值 - 命名为右值引用),因此返回的是左值引用。

在这种情况下,它会导致可能修改文字的情况。使用"universal references"时需要慎重使用转发(或 "forwarding references" )和相关的引用折叠规则。

正如您已经指出的那样,要纠正这种情况,需要正确使用 std::forward 并且返回类型将是预期的类型。


更多详情请访问 std::forward和引用折叠可以找到here on SO .

关于c++ - 为什么这个函数在给定右值参数的情况下返回一个左值引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26354868/

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