Как мне получить пакет параметров шаблона для вывода pass-by-reference, а не pass-by-value?

В следующем классе wrapper принимает указатель на произвольный метод const и возвращает результат вызова этого метода с удалением const. Это можно использовать для генерации соответствующего метода не const...

struct C {
  int x[10];

  int const& get(int i) const { return x[i]; }
  int const& getr(int const& i) const { return x[i]; }

  template<typename T, typename... Ts>
  auto& wrapper(T const& (C::*f)(Ts...) const, Ts... args) {
    return const_cast<T&>((this->*f)(args...));
  }

  int& get(int i) { return wrapper(&C::get, i); }
  int& getr(int const& i) { return wrapper(&C::getr, i); }
};

почти.

Проблема заключается в том, что окончательный метод getr() не может быть скомпилирован, потому что список аргументов, переданный в wrapper(), не подразумевает передачу по ссылке. К тому моменту, когда мы попадаем внутрь wrapper(), компилятор ищет версию пошагового значения getr().

Есть ли уловка?

Ответ 1

Вы можете отличить вперед аргументы функции:

template<typename T, typename... Ts, typename... Args>
auto& wrapper(T const& (C::*f)(Ts...) const, Args&&... args) {
  return const_cast<T&>((this->*f)(std::forward<Args>(args)...));
}

Это достигается путем создания args пакета ссылочных параметров пересылки. Обратите внимание, что нам нужно ввести новый пакет параметров шаблона args для правильного вывода аргументов.