Рассмотрим следующий код:
#include <iostream>
#include <functional>
using namespace std;
template<class T>
void fun(T t)
{
t+=8;
}int main()
{
int i = 0;
fun(ref(i));
cout << i << endl;
}
Этот код печатает «8». Я предполагаю, что t в fun () автоматически конвертируется в int&,
Но если я заменю t+=8
с t=8
программа не скомпилируется.
Зачем?
reference_wrapper<T>
имеет оператор неявного преобразования в T &
, поэтому он будет преобразован в T &
где бы T &
это лучший матч, чем reference_wrapper<T>
,
В расширенном выражении присваивания единственным жизнеспособным оператором является int &operator+=(int &, int)
Итак int &
извлекается.
В выражении присваивания оператор-член reference_wrapper<int>::operator=(const reference_wrapper<int> &)
также доступен, поэтому оператор-член является предпочтительным; Затем компилятор пытается создать эталонную оболочку из константы 8
, который терпит неудачу. Оператор присваивания имеет эффект повторного связывания, что необходимо для таких объектов, как tie
работать как положено.
Это означает, что упаковщики ссылок ближе к ссылкам в таких языках, как Python, чем ссылки C ++:
#include <functional>
#include <iostream>
int main() {
int i = 1, j = 2;
std::ref(i) = j;
std::cout << i << '\n'; // prints '1'
}
Других решений пока нет …