Идеальная пересылка элемента объекта

Предположим, что у меня есть два struct s:

struct X {};
struct Y { X x; }

У меня есть функции:

void f(X&);
void f(X&&);

Как написать функцию g(), которая принимает Y& или Y&&, но совершенную переадресацию X& или X&& в f() соответственно:

template <typename T>
void g(T&& t) {
  if (is_lvalue_reference<T>::value) {
    f(t.x);
  } else {
    f(move(t.x));
  }
}

Приведенный выше код иллюстрирует мое намерение, но не очень масштабируется по мере увеличения числа параметров. Есть ли способ заставить его работать для идеальной пересылки и сделать его масштабируемым?

Ответ 1

template <typename T>
void g(T&& t) {
  f(std::forward<T>(t).x);
}

Ответ 2

Я думаю, что это сработает, хотя я не уверен:

template<class T, class M>
struct mforward {
  using type = M&&; 
};
template<class T, class M>
struct mforward<T&, M> {
  using type = M&; 
};

template <typename T>
void g(T&& t) {
  f(std::forward<typename mforward<T, decltype(t.x)>::type>(t.x));
}