Deducing knowledge of original types, while simultaneously forwarding

Резюме: Я хочу получить функцию, которая выводит точные типы, с которыми она была вызвана, и принимает (например) кортеж, который передает их (типы которых будут отличаться от точных типов, с которыми была вызвана функция).

Я застрял, пытаясь "узнать" с помощью дедукции типы аргументов данной функции, одновременно пересылая их. Мне кажется, что я упускаю что-то важное в том, как это работает.

#include <tuple>
#include <string>
#include <functional>

template <typename ...Args>
struct unresolved_linker_to_print_the_type {
   unresolved_linker_to_print_the_type();
};

void f(int,double,void*,std::string&,const char*) {
}

template <typename F, typename ...Args>
void g1(F func, Args&&... args) {
  unresolved_linker_to_print_the_type<Args...>();
  auto tuple = std::forward_as_tuple(args...);
  unresolved_linker_to_print_the_type<decltype(tuple)>();
}

template <typename F, typename T, typename ...Args>
void g2(F func, const T& tuple, Args... args) {
  unresolved_linker_to_print_the_type<Args...>();
  unresolved_linker_to_print_the_type<decltype(tuple)>();
}

int main() {
  int i;
  double d;
  void *ptr;
  std::string str;
  std::string& sref = str;
  const char *cstr = "HI";

  g1(f, i,d,ptr,sref,cstr);
  g2(f, std::forward_as_tuple(i,d,ptr,sref,cstr),  i,d,ptr,sref,cstr);
}

Что я хотел бы видеть, так это сценарий, когда моя функция (например, g1 или g2) вызывается, она знает и может использовать как исходные типы - int,double,void*,std::string&,const char* так и пересылаемые аргументы.

В данном случае я не могу найти эту информацию в g1 или g2. Ошибка компоновщика (намеренная, чтобы вывести типы) показывает, что в g1 они такие:

int&, double&, void*&, std::string&, char const*&
int&, double&, void*&, std::string&, char const*&

и в g2:

int, double, void*, std::string, char const*
int&, double&, void*&, std::string&, char const*&

Здесь есть две вещи, которые я не понимаю:

  1. Почему ни один из выведенных (через ошибку компоновщика) типов не соответствует тому, что я фактически передал? (int,double,void*,std::string&,const char). Могу ли я вывести, что мне на самом деле передали? Желательно с "естественным" синтаксисом, т.е. все только один раз и ничего явно не выписано. Я могу явно написать:

    g2(f,std::forward_as_tuple(i,d,ptr,sref,cstr),i,d,ptr,sref,cstr))
    

    но это, мягко говоря, "громоздко"!

  2. В g1 наличие && в объявлении сигнатуры функции, похоже, изменяет типы в самом параметре шаблона Args. Сравните это с:

    template 
    void test(T t);
    

    Или:

    template 
    void test(T& t);
    

    используя любой из них с:

    int i;
    test(i);
    

    не изменяет тип T. Почему && изменяет тип самого T, а & - нет?

8
задан Deduplicator 21 October 2018 в 23:14
поделиться