Как пересылать упакованные вариативные аргументы

У меня есть функция, которая принимает переменные аргументы, упакованные в кортеж.

template <class... Args>
void Bottom(tuple<Args&&...> t)
{
}

Является ли Args&& ссылкой для пересылки? т.е. будут ли применяться правила для свертывания ссылок или я просто добавляю && к каждому аргументу в пакете?

И скажем, я хочу вызвать эту функцию из функции, которая, безусловно, получает ссылки для пересылки:

template <class... Args>
void Top(Args&&... args) {
  // 1. Bottom<Pack...>();
  // 2. Bottom<Pack&&...>();
}

какой синтаксис будет лучше, если я не хочу изменять аргументы, 1 или 2?

РЕДАКТИРОВАТЬ

Я использую кортеж только для демонстрации класса, который упаковывает мои параметры. Фактические классы упаковки различаются на разных уровнях иерархии вызовов. Идея использовать using_fwd_as_tuple в качестве ресурса, чтобы узнать, что библиотека делает в этом случае, крутая.


person Lorah Attkins    schedule 09.10.2020    source источник
comment
если вопрос, который вы задали, окажется не тем вопросом, который вы хотели задать, возможно, откройте другой вопрос. Особенно после того, как вы получили ответы, нехорошо вносить правку в духе: Ну, ответ на вопрос есть, но я хочу другой (я преувеличиваю)   -  person 463035818_is_not_a_number    schedule 09.10.2020


Ответы (2)


Я бы сказал, что нет. Я бы использовал std::forward_as_tuple и позволил компилятору сделать вывод:

template <class... Args>
void Top(Args&&... args) {
  Bottom(std::forward_as_tuple(args...));
}
person bartop    schedule 09.10.2020
comment
+1 Потому что я вижу, что делает кортеж вперед, и имитирую это. К сожалению, в моем коде нет кортежей. - person Lorah Attkins; 09.10.2020
comment
Forward as tuple создает кортеж ссылок на аргументы (lvalue или rvalue refs). Я специально хочу сохранить исходные типы, выведенные в функции Top - person Lorah Attkins; 09.10.2020

Нет, tuple<Args&&...> t не являются ссылками для пересылки. Они могут присутствовать только как аргументы верхнего уровня.

Вы ничего не добавляете, вы пытаетесь сопоставить аргументы. Такая функция принимает только кортежи (по значению), которые содержат ссылки на r-значение.

Пример

#include <tuple>
using namespace std;

template <class... Args>
void Bottom(tuple<Args&&...> t)
{
}

// Type your code here, or load an example.
int main(){
    double var=0.0;

    tuple<int,double&,char&&> tup1{1,var,'c'};
    //#1
    //Bottom(tup1);

    tuple<int&&,double&&,char&&> tup2{1,0.0,'c'};
    //#2
    //Bottom(tup2);
    //#3
    Bottom(std::move(tup2));
}
  1. Не компилируется, так как аргументы не могут быть сопоставлены.
  2. Тоже не компилируется. Несмотря на то, что аргументы совпадают, сам кортеж передается по значению, в данном случае путем копирования, а конструктор копирования удаляется при наличии элементов кортежа с r-значением.
  3. Moving is fine, this instantiates this template:
    template<>
    void Bottom<int, double, char>(std::tuple<int &&, double &&, char &&> t)
    {
    }
    
person Quimby    schedule 09.10.2020