Ссылка на значение не работает, когда параметр является пакетом параметров - PullRequest
1 голос
/ 04 марта 2020

Когда я делаю rvalue из пакета параметров шаблона, он не компилируется, но если это «простой» параметр шаблона, он компилируется нормально.

В этом коде for_each_in_tup1 компилируется нормально, но for_each_in_tup3 не. Я не понимаю, почему это не скомпилируется, но G CC 9.2 и V C 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) {
      |                        ~~~~~~~~~~~~~~~^~~

Годболт

1 Ответ

2 голосов
/ 04 марта 2020

В for_each_in_tup1 вы используете ссылку для пересылки :

template< typename Tuple, size_t N = 0>
void for_each_in_tup1( Tuple&& tup ) 

при передаче значения lvalue Tuple будет равно Tuple&, и после объединения ссылок вы получите получить for_each_in_tup1(Tuple&). lvalue может быть привязан к ссылке на lvalue, поэтому этот код работает. Если вы передали rvalue в for_each_in_tup1, параметр будет Tuple&&, и он может принимать только rvalue.

В for_each_in_tup3 есть нормальная ссылка на rvalue, которая может связывать только rvalue. Чтобы вызвать for_each_in_tup3, вы должны привести tup к значению, например, std::move:

for_each_in_tup3(std::move(tup));
...