Как усовершенствовать пересылку переменной-члена
Рассмотрим следующий код:
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));
}
В этом коде фактический объект, который пересылается, является членом, а не объектом. Поскольку переадресация является условным шагом, вы можете посмотреть на эти две статьи: введите описание ссылки здесь введите описание ссылки здесь