Is this the behavior of std :: ref logical?

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 expect the second value to be 7, not 100.

What am I missing?

+65
c ++ c ++ 11 ref
May 08 '16 at 15:08
source share
3 answers

A small modification of f2 gives the key:

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

Now it does what you expect.

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

It does not assign a wrapped link.

In the case of f1 everything works as you expected, because std::reference_wrapper<T> provides a conversion operator for T& that will bind to the implicit right-hand side of int implicit operator+ .

+56
May 08 '16 at 15:15
source share

reference_wrapper has operator = and no explicit constructor, see the documentation .

So, even if this is surprising, this is normal behavior:

f2 redirects the local reference_wrapper to xx .

+11
May 08 '16 at 15:17
source share

arg = xx;

Local arg now refers to (reads as binding to) xx . (And no longer applies to j )

arg += xx;

The implicit operator T& () is used to match the argument operator += and, therefore, the addition is performed on the mentioned object ie j .

Thus, the observed behavior is correct.

+8
May 09 '16 at 6:35
source share



All Articles