18

I am trying to understand how std::ref works.

#include <functional>
#include <iostream>

template <class C>
void func(C c){
    c += 1;
}

int main(){
    int x{3};
    std::cout << x << std::endl;
    func(x);
    std::cout << x << std::endl;
    func(std::ref(x));
    std::cout << x << std::endl;
}

Output : 3 3 4

In the code above, I think the template parameter C for the third function call is instantiated as std::reference_wrapper<int>. While reading the reference, I noticed there is no += operator in std::reference_wrapper<int>. Then, how is c += 1; valid?

xdumaine
  • 10,096
  • 6
  • 62
  • 103
Sungmin
  • 2,499
  • 3
  • 26
  • 32

2 Answers2

20

how is c += 1; valid?

Because reference_wrapper<int> is implicitly convertible to int& via its conversion operator; and implicit conversions are considered for operands if there is no suitable overload for the operand type itself.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • @Sungmin: Indeed, `c` itself can't change type; but `+=` is applied to the result of `c.operator int&()` which will be a reference to target of the `reference_wrapper`. – Mike Seymour May 14 '13 at 11:56
  • 1
    Note this magic only works for operators. For example, if `x` were of class type and had a method `x.foo()`, and you tried to wrap a reference to `x` in a `reference_wrapper` `rx`, you could not just say `rx.foo()`. You would have to say `rx.get().foo()`, which is about as ugly as just using a pointer `px->foo`. So unfortunately `std::reference_wrapper` is not a magical do-all wrapper for references (which is what a lot of people hope to use it for, e.g. [for copying objects with reference members](http://stackoverflow.com/questions/7906127/assignment-operator-with-reference-members)). – Louis Semprini Jan 08 '17 at 10:28
12

std::reference_wrapper<T> has a conversion operator to T&. This means that std::reference_wrapper can be implicitly converted to int& in your example.

juanchopanza
  • 223,364
  • 34
  • 402
  • 480
  • The two answers were uploaded almost the same time. But Mike Seymour's answer is a little bit faster. Apart from that, I cannot determine which one to pick. Sorry for that. Thanks anyway. – Sungmin May 14 '13 at 12:02
  • 1
    @Sungmin You are welcome. I think Seymour's answer is better anyway: he explains about the operators overloads and operands, which I failed to do. – juanchopanza May 14 '13 at 12:17