Как усовершенствовать пересылку переменной-члена

Рассмотрим следующий код:

template<typename T> void foo(T&& some_struct)
{
    bar(std::forward</* what to put here? */>(some_struct.member));
}

В случае пересылки всей структуры я бы сделал std::forward<T>(some_struct). Но как получить правильный тип при пересылке члена?

У меня была идея использовать decltype(some_struct.member), но, похоже, это всегда приводит к базовому типу этого члена (как определено в определении структуры).

Ответ 1

Доступ к членам является сохранением категории значения. Если объектное выражение является lvalue, то и доступ к члену, в противном случае это xvalue (как результат std::move). То же самое можно сказать и о члене в результате пересылки объекта.

std::forward<T>(some_struct).member

Ответ 2

Доступ к члену делает правильную вещь здесь: вам просто нужен std::forward<T>(some_struct).member.

Протестировано с:

template <class... >
struct check;

struct Foo {
    int i;
};

template <class T>
void bar(T &&f) {
    // fatal error: implicit instantiation of undefined template 'check<int &&>'
    check<decltype((std::forward<T>(f).i))>{};
}

int main() {
    bar(Foo{42});
}

Ответ 3

Как объясняет @StoryTeller, если вы пересылаете структуру, то категория значения элемента сохраняется (я думаю, это важно иметь в виду). Но как получить правильный тип при пересылке члена? Вы могли бы сделать что-то вроде этого:

template <typename T>
void foo(T&& some_struct) {
    bar(std::forward<decltype(std::declval<T>().member)>(some_struct.member));
}

В этом коде фактический объект, который пересылается, является членом, а не объектом. Поскольку переадресация является условным шагом, вы можете посмотреть на эти две статьи: введите описание ссылки здесь введите описание ссылки здесь