为什么这些断言适用于以下代码?通用引用应绑定到左值引用var express = require("express");
var app = express();
var body = require("body-parser");
var https = require("https");
app.get("/results", function (req, res) {
https.get("https://www.omdbapi.com/?apikey=d49698c3&s=harry", function (response) {
response.on("data", function (data) {
var got = JSON.parse(data);
res.send(got.Title);
})
})
});
,并从run(T& a)
复制对象b
。但是,a
函数中两个对象地址“ a”和“ b”相同。使用C ++ 11/14/17 / 2a gcc-9.2和clang ++-6.0进行了测试。标准的哪一部分说这是有效的?没有发现任何相关内容。
run()
答案 0 :(得分:2)
但是
run()
函数中两个对象的地址“ a”和“ b”相同。
在传递左值时,T
是deduced作为左值引用,即int&
。 (int& &&
collapses到int&
,因此功能参数a
的类型为int&
。)然后将b
声明为对a
。
传递右值时,T
推导为int
。 (因此,函数参数a
的类型为int&&
。)然后将b
声明为从a
复制的自变量。
答案 1 :(得分:1)
在run(value)
中,value
是一个左值,它必须与T&&
匹配。左值不能绑定到右值引用,因此T = int
和T = int&&
不会这样做。唯一有效的是T&& = int&&
。由于引用折叠,因此对左值引用的右值引用就是左值引用,因此T = int&
的实例化如下:
run
很明显,断言总是会通过。现在,对于template<>
void run<int&>(int &a) {
int &b{a}; // expanding std::forward
++b;
assert(b == a);
assert(&b == &a);
}
,该参数确实是一个右值,您得到run(std::move(value))
。然后
T = int
这当然会失败。也许您应该替换
template<>
void run<int>(int &&a) {
int b{std::move(a)};
++b;
assert(b == a);
assert(&b == &a);
}
使用
T b{std::forward<T>(a)};
这将从std::decay_t<T> b{std::forward<T>(a)};
中删除引用(确保T
是一个新的(已复制/移动的)对象),并且还将处理数组和函数(通过使b
成为指针,即使{{ 1}}不是)。
您是否需要它们,但是[temp.deduct.call]/3
讨论了转发引用的模板推导,[dcl.init.list]/3.9
说,列表初始化引用只是将其绑定到初始化列表的元素。 [forward]
也很好地解释了b
。基本上,如果a
是左值引用,则std::forward<T>
是左值,否则是xvalue(一种rvalue)。 (基本上是有条件的T
。)