http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56112
--- Comment #6 from Jonathan Wakely <redi at gcc dot gnu.org> 2013-01-27 16:25:36 UTC --- (In reply to comment #5) > Uhhmm, I wasn't considering the fact that the testcases added for 53339 are > now > xfailed?!? That was me: http://gcc.gnu.org/ml/libstdc++/2013-01/msg00035.html > So what? If that's the case (for now at least) we could as well > revert the core of the 53339 changes, that is go back to the 4.7 situation and > just use std::_Select1st<value_type>?!? Yes, I suppose we could, but we'd need to revert the changes to stl_function.h so that it doesn't derive from unary_function in C++11 mode. I think having a simple __detail::_Select1st<_Pair> that just does what the hash tables need is cleaner, and it can be made simpler than your patch because it doesn't need to use perfect forwarding: template<typename _Pair> struct _Select1st { auto operator()(const _Pair& __x) const -> decltype(std::get<0>(__x)) { return std::get<0>(__x); } }; Or we could simplify it even further const typename _Pair::first_type& operator()(const _Pair& __x) const { return __x.first); } This would prevent fancy custom uses of _Hashtable, for example _Hashtable<int, std::tuple<int, int, int>, ...>, but I don't think we need or want to do that anyway. My testcase for this bug reveals another problem in an area we've had recurring problems: _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, _RehashPolicy, _Traits>:: _M_insert(_Arg&& __v, std::true_type) { const key_type& __k = this->_M_extract()(__v); __hash_code __code = this->_M_hash_code(__k); size_type __bkt = _M_bucket_index(__k, __code); __node_type* __n = _M_find_node(__bkt, __k, __code); With my testcase __k is a dangling reference, because the call to _M_extract creates a temporary, __k binds to a member of that temporary, then the temporary goes out of scope. Valgrind will show errors for this modified testcase which allocates memory in the temporary: #include <unordered_map> #include <string> struct S { operator std::pair<const std::string, int>() const { return {"a", 0}; } }; int main() { S s[1]; std::unordered_map<std::string, int> m(s, s+1); // error } To fix this we need to extract the key and set __code, __bkt and __n in a single statement before the temporary goes out of scope, e.g. using a lambda just for a proof of concept: __hash_code __code; size_type __bkt; __node_type* __n; auto __find_node = [&](const key_type& __k) { __code = this->_M_hash_code(__k); __bkt = _M_bucket_index(__k, __code); __n = _M_find_node(__bkt, __k, __code); }; __find_node(this->_M_extract()(value_type(__v))); So I think we want something like your comment 4 attachment, with a simpler _Select1st, and fixing the memory bug. I'm testing that now ...