Is this std::ref behaviour logical?

C++C++11Ref

C++ Problem Overview


Consider this code:

#include <iostream>
#include <functional>
 
int xx = 7;
 
template<class T>
void f1(T arg)
{
    arg += xx;
}
 
template<class T>
void f2(T arg)
{
    arg = xx;
}
 
int main()
{
    int j;
 
    j=100;
    f1(std::ref(j));
    std::cout << j << std::endl;
 
    j=100;
    f2(std::ref(j));
    std::cout << j << std::endl;
}

When executed, this code outputs

107
100

I would have expected the second value to be 7 rather than 100.

What am I missing?

C++ Solutions


Solution 1 - C++

A small modification to f2 provides the clue:

template<class T>
void f2(T arg)
{
    arg.get() = xx;
}

This now does what you expect.

This has happened because std::ref returns a std::reference_wrapper<> object. The assignment operator of which rebinds the wrapper. (see http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/operator%3D)

It does not make an assignment to the wrapped reference.

In the f1 case, all is working as you expected because a std::reference_wrapper<T> provides a conversion operator to T&, which will bind to the implicit right hand side of ints implicit operator+.

Solution 2 - C++

reference_wrapper has operator = and a non explicit constructor, see documentation.

So, even if it is surprising, it is the normal behaviour:

f2 rebinds the local reference_wrapper to xx.

Solution 3 - C++

> arg = xx;

Local arg now refers to (read as binds with) xx. (And no more refers to j)

> arg += xx;

Implicit operator T& () is applied to match the argument of operator += and hence addition is performed on referred object i.e. j.

So the observed behaviour is correct.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionoz1czView Question on Stackoverflow
Solution 1 - C++Richard HodgesView Answer on Stackoverflow
Solution 2 - C++Jarod42View Answer on Stackoverflow
Solution 3 - C++Mohit JainView Answer on Stackoverflow