12

Is it legal to have an unordered_map with the value type being a reference C++11?

For example std::unordered_map<std::string, MyClass&>

I have managed to get this to compile with VS2013 however I'm not sure whether it's supposed to as it is causing some strange runtime errors. For example vector subscript out of range is thrown when trying to erase an element.

Some googling resulted in finding out that you can't have a vector of references but I can't find anything about an unordered_map.

Update

Further experimentation has shown that the vector subscript out of range was not related to the unordered_map of references as it was a bug in my code.

11
  • 1
    Just use std::reference_wrapper. Commented Jul 13, 2014 at 2:33
  • 11
    You may declare such a map, and most but not all operations on it should work. You can't use operator[] as it requires the mapped type to be DefaultConstructible (and references aren't). You can't brace-initialize this map, or assign one map to another, as this requires mapped type to be CopyAssignable. Commented Jul 13, 2014 at 3:04
  • 1
    @Igor Most containers does not require (Copy/Move)Assignable, they work fine with (Copy/Move)Constructible and assignement or brace initialisation is fine. operator[] of maps are the only exception needing DefaultConstructible and (Copy/Move)Assignable. Commented Jul 13, 2014 at 9:56
  • 1
    @galop1n Well, it might not be necessary with a particular compiler and standard library implementation. But a program that takes advantage of this flexibility is not a valid C++11 program. Practically speaking, it's non-portable; it happens to work with this implementation, but it's not guaranteed to work with other conforming implementations. Commented Jul 14, 2014 at 0:24
  • 1
    @IgorTandetnik You should make an answer of your first comment, it was very useful and I would be happy to upvote it. Commented Apr 28, 2017 at 8:12

1 Answer 1

6

map and unordered_map are fine with references, here a working example :

#include <iostream> #include <unordered_map> using UMap = std::unordered_map<int,int&>; int main() { int a{1}, b{2}, c{3}; UMap foo { {1,a},{2,b},{3,c} }; // insertion and deletion are fine foo.insert( { 4, b } ); foo.emplace( 5, d ); foo.erase( 4 ); foo.erase( 5 ); // display b, use find as operator[] need DefaultConstructible std::cout << foo.find(2)->second << std::endl; // update b and show that the map really map on it b = 42; std::cout << foo.find(2)->second << std::endl; // copy is fine UMap bar = foo; // default construct of bar then operator= is fine too std::cout << bar.find(2)->second << std::endl; } 
Sign up to request clarification or add additional context in comments.

1 Comment

Doesn't seem to work with objects. Trying this with std::thread just gives me error: value-initialization of reference type ‘std::thread&’

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.