@Quad_Tree

Как принимать аргументом rvalue и lvalue?

В книге Скотта Майерса Effective C++ приводится пример вот такой функции с использованием universal reference:
template<typename Container, typename Index>
decltype(auto) authAndAccess(Container&& c, Index i) {
    return std::forward<Container>(c)[i];
}

Universal reference как я понимаю используется для того, чтобы в случае передачи lvalue мы получали ссылку на контейнер, а в случае rvalue мы получали копию контейнера. Проблема заключается в том std::forward в любом случае возвращает ссылку на элемент контейнера. То есть:
decltype(auto) variable = fnt(vector<string>{"one", "two"}, 0);

Тип variable будет string&, что по сути является ссылкой на локальный объект функции, что приводит к SIGSEGV. Как заставить функцию возвращать копию элемента в случае rvalue и ссылку на элемент в случае, если передан lvalue.
  • Вопрос задан
  • 122 просмотра
Пригласить эксперта
Ответы на вопрос 1
@Fil
Universal reference позволяет передавать ссылки обоих типов, используя правила вывода типа ссылки для шаблонного параметра. Про forward я уже написал в комментарии. Есть некоторая сложность в том, чтобы реализовать вашу хотелку в одной функции. Потому что тип контейнера должен влиять на тип возвращаемого значения этого контейнера. Самый простой вариант написать 2 перегрузки:
template<typename Container, typename Index>
auto authAndAccess(Container&& c, Index i) {
    return std::forward<Container>(c)[i];
}

template<typename Container, typename Index>
decltype(auto) authAndAccess(Container& c, Index i) {
    return std::forward<Container>(c)[i];
}

В первом случае мы возвращаем по значению, во втором - по ссылке.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы