当参数是参数包时,右值引用不起作用
rvalue reference not working when parameter is a parameter pack
当我从模板参数包中生成右值时,它无法编译,但如果它是 'simple' 模板参数,则可以正常编译。
在此代码中,for_each_in_tup1
可以正常编译,但 for_each_in_tup3
不能。我不明白为什么这不会编译,但 GCC 9.2 和 VC v142 都认为这是错误的。
为什么这个语法无效?
这个例子:
#include <tuple>
using namespace std;
template< typename Tuple, size_t N = 0>
void for_each_in_tup1( Tuple&& tup ) {
if constexpr(N < tuple_size<decay_t<Tuple>>::value)
for_each_in_tup1<Tuple, N + 1>(forward<Tuple>(tup));
}
template< template<typename...> typename Tuple, typename... Ts>
void for_each_in_tup2( const Tuple<Ts...>& tup) {
}
template< template<typename...> typename Tuple, typename... Ts>
void for_each_in_tup3( Tuple<Ts...>&& tup) {
}
void test_lazy() {
tuple<uint32_t, uint32_t> tup;
for_each_in_tup1(tup);
for_each_in_tup2(tup);
for_each_in_tup3(tup);
}
失败:
<source>:20:22: error: cannot bind rvalue reference of type 'std::tuple<unsigned int, unsigned int>&&' to lvalue of type 'std::tuple<unsigned int, unsigned int>'
20 | for_each_in_tup3(tup);
| ^~~
<source>:15:39: note: initializing argument 1 of 'void for_each_in_tup3(Tuple<Ts ...>&&) [with Tuple = std::tuple; Ts = {unsigned int, unsigned int}]'
15 | void for_each_in_tup3( Tuple<Ts...>&& tup) {
| ~~~~~~~~~~~~~~~^~~
在 for_each_in_tup1
中,您正在使用 转发参考:
template< typename Tuple, size_t N = 0>
void for_each_in_tup1( Tuple&& tup )
当你传递左值时,Tuple
被推导为Tuple&
,在引用合并后你将得到for_each_in_tup1(Tuple&)
。左值可以绑定到左值引用,这就是这段代码有效的原因。如果您将右值传递给 for_each_in_tup1
,参数将是 Tuple&&
,并且它只能接受右值。
在for_each_in_tup3
中有普通的右值引用,它只能绑定右值。
要调用 for_each_in_tup3
,您必须将 tup
转换为右值,例如 std::move
:
for_each_in_tup3(std::move(tup));
当我从模板参数包中生成右值时,它无法编译,但如果它是 'simple' 模板参数,则可以正常编译。
在此代码中,for_each_in_tup1
可以正常编译,但 for_each_in_tup3
不能。我不明白为什么这不会编译,但 GCC 9.2 和 VC v142 都认为这是错误的。
为什么这个语法无效?
这个例子:
#include <tuple>
using namespace std;
template< typename Tuple, size_t N = 0>
void for_each_in_tup1( Tuple&& tup ) {
if constexpr(N < tuple_size<decay_t<Tuple>>::value)
for_each_in_tup1<Tuple, N + 1>(forward<Tuple>(tup));
}
template< template<typename...> typename Tuple, typename... Ts>
void for_each_in_tup2( const Tuple<Ts...>& tup) {
}
template< template<typename...> typename Tuple, typename... Ts>
void for_each_in_tup3( Tuple<Ts...>&& tup) {
}
void test_lazy() {
tuple<uint32_t, uint32_t> tup;
for_each_in_tup1(tup);
for_each_in_tup2(tup);
for_each_in_tup3(tup);
}
失败:
<source>:20:22: error: cannot bind rvalue reference of type 'std::tuple<unsigned int, unsigned int>&&' to lvalue of type 'std::tuple<unsigned int, unsigned int>'
20 | for_each_in_tup3(tup);
| ^~~
<source>:15:39: note: initializing argument 1 of 'void for_each_in_tup3(Tuple<Ts ...>&&) [with Tuple = std::tuple; Ts = {unsigned int, unsigned int}]'
15 | void for_each_in_tup3( Tuple<Ts...>&& tup) {
| ~~~~~~~~~~~~~~~^~~
在 for_each_in_tup1
中,您正在使用 转发参考:
template< typename Tuple, size_t N = 0>
void for_each_in_tup1( Tuple&& tup )
当你传递左值时,Tuple
被推导为Tuple&
,在引用合并后你将得到for_each_in_tup1(Tuple&)
。左值可以绑定到左值引用,这就是这段代码有效的原因。如果您将右值传递给 for_each_in_tup1
,参数将是 Tuple&&
,并且它只能接受右值。
在for_each_in_tup3
中有普通的右值引用,它只能绑定右值。
要调用 for_each_in_tup3
,您必须将 tup
转换为右值,例如 std::move
:
for_each_in_tup3(std::move(tup));