3

So once an std::pair with at least one reference variable has been initialized, for example like this:

int a = 53;
int b = 42;
std::pair<int, int&> foo(33, a);

Is there a way to change where the reference variable is pointing?

Assignment:

foo = std::make_pair(33, std::ref(b));

and swapping:

std::pair<int, int&> bar(33, b);
foo.swap(bar);

appear to just move the new contents to a and leave second member of foo pointing where it was before (a), therefore not doing what I'm trying to achieve here. I am aware that references cannot be rebound as answered here, but this isn't what I am trying to do here. What I'm trying to do is make a new pair and assign its contents to an existing one which technically isn't the same thing.

Thanks in advance!

Acorn
  • 24,970
  • 5
  • 40
  • 69
peeto
  • 41
  • 3
  • 2
    Why not use a reference_wrapper instead? – cigien Oct 03 '20 at 19:00
  • 2
    I'd recommend using `std::reference_wrapper` as the type instead of `int&` – tenfour Oct 03 '20 at 19:00
  • "which technically isn't the same thing" yes it is.... what do you think the `std::pair` assignment operator does under the hood? – JHBonarius Oct 03 '20 at 19:12
  • 2
    *"which technically isn't the same thing"* -- false. It doesn't matter if the reference is inside a pair or not. Attempting to assign a new reference to an existing reference *is* an attempt to rebind the reference. You just threw on an extra layer of obfuscation than most. – JaMiT Oct 03 '20 at 19:12

3 Answers3

5

References always work the same way in C++.

int a;
int &b=a;

b will always be a reference to a, until b goes out of scope and gets destroyed.

References in std::pairs, or anywhere else, work the same way. Once they are bound, they will always refer to the same object they were bound to. Assigning to a reference will always assign to the referenced object.

It also doesn't matter what the reference is to, to an int, to a char, or to any other objects. References always work the same way, in this respect.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148
1

You shouldn't rebind references...

...but you kinda can. Trying to assign a reference is impossible, but you can achieve the same effect

new (&foo) std::pair<int, int&>(33, b);

will destroy the old pair and construct a new pair referencing b. You are correct, a pair with a reference member isn't the same as a plain reference.

There are many rules, caveats and ways you can make a mistake here. Just accept that references aren't meant for reassignment.

†But not call the destructor, which is fine here. Placement new is less error prone in C++20 due to this.

Passer By
  • 19,325
  • 6
  • 49
  • 96
  • 1
    Pre-C++20 the resulting reference can't be used without `std::launder`ing it every time. And I my own code I'd probably call the destructor, for extra clarity. – HolyBlackCat Oct 03 '20 at 21:05
0

What I'm trying to do is make a new pair and assign its contents to an existing one which technically isn't the same thing.

You can do that. The assignment operator of the pair assigns each member. When a reference member is assigned, the referred object is assigned. If you want this assignment to rebind the member of that pair, then you want what you know is not possible.

eerorika
  • 232,697
  • 12
  • 197
  • 326