Существует ряд проблем с кодом, которым вы поделились.
Первая проблема заключается в том, что вы возвращаете ссылку на объект, который больше не будет существовать, когда ваша функция вернется.std::ref
возвращает std::reference_wrapper
, который выйдет из области видимости.std::reference_wrapper
- это объект, который дает некоторые функциональные возможности ссылочного типа, все еще ведя себя как объект.Он имеет семантику перемещения, поэтому правильное использование будет возвращать std::reference_wrapper
по значению.
#include<functional>
struct S {
int m_i = 2;
auto get2() { return std::ref(m_i); }
};
Хотя, как отмечали другие, std::ref
здесь на самом деле не требуется.Вы можете просто вернуть ссылку на m_i
напрямую.Если пользователю действительно нужен std::reference_wrapper
для этого int
, он может сам позвонить std::ref
со ссылкой на предоставленную вами m_i
.
struct S {
int m_i = 2;
int & get2() { return m_i; }
};
Но это не единственная проблема сваш код.Если вы решите первую проблему и вернете std::reference_wrapper
по значению, вы по-прежнему неправильно используете std::reference_wrapper::operator=
.Этот оператор не присваивает новое значение указанному объекту.Вместо этого он перепривязывает ссылку для ссылки на другой экземпляр.Правильным использованием будет использование get()
для получения правильного присваиваемого int&
из std::reference_wrapper
:
#include<functional>
#include<iostream>
struct S {
int m_i = 2;
auto get2() { return std::ref(m_i); }
};
int main() {
S s;
s.get2().get() = 4;
std::cout << s.m_i << std::endl;
return 0;
}
Но как насчет сообщения об ошибке?Компилятор видит, что единственный operator=
, существующий для std::reference_wrapper
, - это тот, который принимает еще std::reference_wrapper
.Таким образом, он пытается неявным образом преобразовать 4
в std::reference_wrapper
единственным возможным способом, пытаясь использовать конструктор, который принимает один аргумент.Однако невозможно создать std::reference_wrapper
для литерала, подобного 4
(или значениям в целом).Для этого нужно правильное значение.Этого можно избежать, объявив конструктор, который принимает rvalue ссылки на упакованный тип (в данном случае int
), и удалив его.Попытка использовать этот конструктор приведет к ошибке, которую вы видите.Удаленная функция - std::reference_wrapper<int>::reference_wrapper<int>(int&&)
, которая вызывается преобразованием, введенным компилятором.