1

While doing code maintenance I found code like this:

auto networkEntry = _networkEntries[key];
networkEntry.port = port;
networkEntry.scope = scope;

The map data type used for _networkEntries has two overloaded versions of the operator[]:

template<class T>
class Map {
    // ... simplified STD compatible container ...
    T & Map::operator[](const Key & key);
    const T Map::operator[](const Key & key) const;
};

The data type used in the map is a simple struct.

Now I just wondered, the returned value for auto could be a copy of the data structure, or a reference to the data structure. If a copy is returned, the assignments would not affect the stored values in the map.

I have three related question for this case:

  • Can I know or test which version of the operator[] was used?
  • Which C++ rules do apply here?
  • Is there a way, using auto, to make sure the reference is used?
Flovdis
  • 2,945
  • 26
  • 49

2 Answers2

7
auto networkEntry = _networkEntries[key];

Here networkEntry will never be a reference type, as auto type deduction rules follow template argument deduction rules.

In short, you need to either say:

  • auto& x = y;

    • Will compile only if y can be bound to an lvalue reference.
  • auto&& x = y;

    • Will always deduce a reference type, either lvalue/rvalue reference depending on the value category of y.
  • decltype(auto) x = y;

    • Will deduce exactly the type of y - it can deduce a reference or a value type. See What are some uses of decltype(auto)?.

    • As Yakk said, if y is not a reference type, x becomes an rvalue reference bound to the non-reference temporary y.

In order to deduce a reference.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • 1
    Posh answer, +1, you might want to wack something about `const` in though. – Bathsheba Jan 11 '18 at 13:26
  • You should be clear with `auto&&` that if `y` is "not a reference type" (ok, a prvalue, but anyone asking this question doesn't know what a prvalue is), `x` becomes an rvalue reference bound to the non-reference temporary `y`. – Yakk - Adam Nevraumont Jan 11 '18 at 15:08
  • Good answer. Since you were hitting all the bases, might as well mention 'const auto &' – Gem Taylor Jan 11 '18 at 17:45
3
  1. If the implied this pointer at the calling site is const, then the const version of operator[] will be called, else the non-const version is called. So if the function containing your code is const, and _networkEntries is a member variable of that class, then the const version will be called.

  2. As above.

  3. If you want a reference, then use auto& not auto for the type at the calling site: auto& networkEntry = _networkEntries[key];.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483