5
template <typename T> void myswap(T a,T b) { T temp = a; a = b; b = temp; } int main() { int m(20),n(30); myswap(ref(m),ref(n)); //m is still 20 and n is still 30 } 

Why have not the values of m and n interchanged? Passing a value wrapped in std::ref to an INCREMENT function results in value change in the original variable (variable in the stack frame that calls INCREMENT function). Or, Is std::ref usage is restricted/limited?

0

3 Answers 3

8

std::ref (and its associated std::reference_wrapper) is a tool designed for very specific use cases in the standard library and should only be used for those; if you want to use it in your own places, you have to understand it in detail and respect what it does.

Fundamentally, a reference_wrapper is much closer to a pointer than a reference. So substitute a pointer in your swap function and you'll see that there's no reason to assume that it would actually swap:

void myswap(int* a, int* b) { int* temp = a; a = b; b = temp; } 
Sign up to request clarification or add additional context in comments.

1 Comment

The first sentence is slightly misleading. Of course std::ref is not limited to the standard library (as you also note it after it)
4

Your code creates two temporary std::reference_wrapper objects and swaps them, so they refer to different objects. All that happens is you swap two reference_wrapper objects, not their targets.

If you manually write what the function template will generate the reason for the behaviour should be obvious:

void myswap(std::reference_wrapper<int> a, std::reference_wrapper<int> b) { std::reference_wrapper<int> temp = a; a = b; b = a; } 

Obviously this doesn't change the int objects, only the reference_wrapper objects.

If what you're trying to do is force myswap to take references you need to call myswap<int&>(m, n), you can't emulate that by using reference_wrapper. But you should really fix myswap, because it's pretty useless the way it's written now.

4 Comments

Indeed, but should not the temporary be pointing to m and n created in the penultimate stack frame?. Pass a variable wrapped in std::ref to a increment function and you will see the value wud have updated. Ain't a temporary created in increment function? Then, how the change is reflected in original variable.
@Jon: Yes, it DOES take 'by value'. template <typename T> void incrementer(T a) { ++a; } int a = 20; incrementer(ref(a)); //a is 21 now
reference_wrapper doesn't support an increment operator, so the increment function causes a conversion to int& and increments the target. The swap function only uses the copy constructor and copy assignment, which reference_wrapper does support, so those operations work on the reference_wrapper directly, not on the target.
No it doesn't. Look at cplusplus.com/reference/functional/reference_wrapper and tell me where you see operator++ declared. The ++bar excample cause a conversion to int& and increments the int. Read my previous comment again. "Incrementing a reference_wrapper" doesn't make sense, so instead it changes the thing it refers to.
1

Your myswap takes the elements by value.

Essentially you swap the two references (std::reference_wrapper s) at the local scope of the function.

The values they point to won't change.


template <typename T> void incrementer(T a) { ++a; } int a = 20; 

In this case there's a conversion to int& with:

operator T& () const noexcept { return *_ptr; } 

In your code, on the other hand:

T temp = a; 

will simply call the copy constructor, which copies the underlying pointer:

reference_wrapper(const reference_wrapper&) noexcept = default; 

then, on the next lines you again copy the pointer:

reference_wrapper& operator=(const reference_wrapper& x) noexcept = default; 

5 Comments

@Karoly: I am passing a reference_wrapper<int> to the function. not plain integer. stackoverflow.com/questions/26766939/… (about reference_wrapper and its benefits).
@101010: Isn't that what I was saying? Let me edit to make it obvious.
Yes, they take elements (of type std::ref) by value. But a copy for m and n is not created in myswap function. The two new references are still pointing to m & n created in penultimate stack frame.
Yes... We agree on all that.
@DIVAKARVENKATRAMANI, yes of course, I don't understand why you expect anything different. Maybe my answer makes it clear.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.