[rvalue引用在参数是参数包时不起作用

问题描述 投票:0回答:1

当我从模板参数包中生成右值时,它不会编译,但是如果它是一个'简单'模板参数,则可以正常编译。

在此代码中,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) {
      |                        ~~~~~~~~~~~~~~~^~~

godbolt

c++ c++17 variadic-templates
1个回答
1
投票

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));
© www.soinside.com 2019 - 2024. All rights reserved.