http://gcc.gnu.org/bugzilla/show_bug.cgi?id=56613
Bug #: 56613 Summary: [4.8 Regression] map::operator[](key_type&&) fails with custom allocator Classification: Unclassified Product: gcc Version: 4.8.0 Status: UNCONFIRMED Keywords: rejects-valid Severity: normal Priority: P3 Component: libstdc++ AssignedTo: unassig...@gcc.gnu.org ReportedBy: r...@gcc.gnu.org This program is valid in C++03 and C++11 but can't be compiled with trunk using -std=c++11 #include <map> template<typename T> struct alloc { typedef T value_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef unsigned size_type; typedef int difference_type; template<typename U> struct rebind { typedef alloc<U> other; }; alloc() { } template<typename U> alloc(const alloc<U>&) { } pointer allocate(size_type n, const void* = 0) { return std::allocator<T>().allocate(n); } void deallocate(pointer p, size_type n) { std::allocator<T>().deallocate(p, n); } size_type max_size() const { return -1; } void construct(pointer p, const T& t) { new ((void*) p) T(t); } void destroy(pointer p) { p->~T(); } }; template<typename T, typename U> bool operator==(alloc<T>, alloc<U>) { return true; } template<typename T, typename U> bool operator!=(alloc<T>, alloc<U>) { return false; } int main() { std::map<int, int, std::less<int>, alloc<int> > m; m[1]; } $ g++-4.8 -std=c++11 map.cc In file included from /home/redi/gcc/4.x/include/c++/4.8.0/map:60:0, from map.cc:1: /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h: In instantiation of 'std::_Rb_tree_node<_Val>* std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_create_node(_Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = alloc<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_Link_type = std::_Rb_tree_node<std::pair<const int, int> >*]': /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:1662:64: required from 'std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::_M_emplace_hint_unique(std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator, _Args&& ...) [with _Args = {const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>}; _Key = int; _Val = std::pair<const int, int>; _KeyOfValue = std::_Select1st<std::pair<const int, int> >; _Compare = std::less<int>; _Alloc = alloc<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator = std::_Rb_tree_iterator<std::pair<const int, int> >; std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::const_iterator = std::_Rb_tree_const_iterator<std::pair<const int, int> >]' /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_map.h:484:8: required from 'std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type& std::map<_Key, _Tp, _Compare, _Alloc>::operator[](std::map<_Key, _Tp, _Compare, _Alloc>::key_type&&) [with _Key = int; _Tp = int; _Compare = std::less<int>; _Alloc = alloc<int>; std::map<_Key, _Tp, _Compare, _Alloc>::mapped_type = int; std::map<_Key, _Tp, _Compare, _Alloc>::key_type = int]' map.cc:41:8: required from here /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:403:8: error: no matching function for call to 'alloc<std::_Rb_tree_node<std::pair<const int, int> > >::construct(std::_Rb_tree_node<std::pair<const int, int> >*&, const std::piecewise_construct_t&, std::tuple<int&&>, std::tuple<>)' _M_get_Node_allocator().construct(__tmp, ^ /home/redi/gcc/4.x/include/c++/4.8.0/bits/stl_tree.h:403:8: note: candidate is: map.cc:28:10: note: void alloc<T>::construct(alloc<T>::pointer, const T&) [with T = std::_Rb_tree_node<std::pair<const int, int> >; alloc<T>::pointer = std::_Rb_tree_node<std::pair<const int, int> >*] void construct(pointer p, const T& t) { new ((void*) p) T(t); } ^ map.cc:28:10: note: candidate expects 2 arguments, 4 provided The problem is that stl_map.h uses piecewise construction for the pair object, which calls alloc::construct with four arguments, incorrectly assuming that all allocators in C++11 have a variadic construct() member. It's easily fixed by changing the C++11 version of _M_create_node to use allocator_traits::construct: std::allocator_traits<_Node_allocator>:: construct(_M_get_Node_allocator(), __tmp, std::forward<_Args>(__args)...); (For 4.9 I was going to make all the RB-trees allocator-aware, but this regression needs to be fixed for 4.8 without the rest of the allocator changes)