
This is about STL containers and allocators. It looks like a mistake in the STL containers but I don't think there is any possible workarounds if the Boost library is based on it. When I look at the code of GCC's std::list: template<typename _Tp, typename _Alloc> void _List_base<_Tp, _Alloc>:: _M_clear() { typedef _List_node<_Tp> _Node; _Node* __cur = static_cast<_Node*>(_M_impl._M_node._M_next); while (__cur != &_M_impl._M_node) { _Node* __tmp = __cur; __cur = static_cast<_Node*>(__cur->_M_next); #if __cplusplus >= 201103L _M_get_Node_allocator().destroy(__tmp); #else _M_get_Tp_allocator().destroy(std::__addressof(__tmp->_M_data)); #endif _M_put_node(__tmp); } } I think it should make use of the allocator's specific pointer as such: template<typename _Tp, typename _Alloc> void _List_base<_Tp, _Alloc>:: _M_clear() { typedef _List_node<_Tp> _Node; typedef typename _Alloc::rebind<_Node>::other::pointer _NodePtr; _NodePtr __cur = static_cast<_NodePtr>(_M_impl._M_node._M_next); while (__cur != &_M_impl._M_node) { _NodePtr __tmp = __cur; __cur = static_cast<_NodePtr>(__cur->_M_next); #if __cplusplus >= 201103L _M_get_Node_allocator().destroy(__tmp); #else _M_get_Tp_allocator().destroy(std::__addressof(__tmp->_M_data)); #endif _M_put_node(__tmp); } } Meanwhile I don't think there is any workaround possible for this for use of an allocator with specific pointer in Boost?

Phil Bouchard wrote:
I think [std::list etc] should make use of the allocator's specific pointer
In C++03, containers were allowed to assume that allocator::pointer == value_type*. This is not true since C++11, where it should use allocator::pointer via allocator_traits. A subtlety is that in the code you posted you're dealing with node pointers, not value_type pointers. I'm not sure what's going on there. My first thought was that you were looking at a pre-11 version of libstdc++, but I see a #if that suggests otherwise. Maybe others can comment. You might like to look at how Boost.Container works. It should use allocator::pointer even on C++03. Note that trying to use a smart pointer for allocator::pointer is unlikely to work in general, e.g. you can't use shared_ptr, because the semantics are not what the container expects. The most common use for redefining allocator::pointer that I've seen is to store offset in memory-mapped files and similar. Regards, Phil.

On 02/18/2016 06:30 AM, Phil Endecott wrote:
Phil Bouchard wrote:
I think [std::list etc] should make use of the allocator's specific pointer
In C++03, containers were allowed to assume that allocator::pointer == value_type*. This is not true since C++11, where it should use allocator::pointer via allocator_traits.
A subtlety is that in the code you posted you're dealing with node pointers, not value_type pointers. I'm not sure what's going on there. My first thought was that you were looking at a pre-11 version of libstdc++, but I see a #if that suggests otherwise. Maybe others can comment.
You might like to look at how Boost.Container works. It should use allocator::pointer even on C++03.
Note that trying to use a smart pointer for allocator::pointer is unlikely to work in general, e.g. you can't use shared_ptr, because the semantics are not what the container expects. The most common use for redefining allocator::pointer that I've seen is to store offset in memory-mapped files and similar.
Thanks for your input... I am trying out boost::container::... right now and it is not a trivial task to use a smart pointers inside containers but I think it is possible. I saw functions like to_raw_pointer() were user before calling the allocator's constructors & destructors... I believe this should be cleaned up sooner or later but for now I think I can survive by overloading only the allocate & deallocate functions.

On 2016-02-18 7:09 PM, Phil Bouchard wrote:
On 02/18/2016 06:30 AM, Phil Endecott wrote:
Phil Bouchard wrote:
I think [std::list etc] should make use of the allocator's specific pointer
In C++03, containers were allowed to assume that allocator::pointer == value_type*. This is not true since C++11, where it should use allocator::pointer via allocator_traits.
A subtlety is that in the code you posted you're dealing with node pointers, not value_type pointers. I'm not sure what's going on there. My first thought was that you were looking at a pre-11 version of libstdc++, but I see a #if that suggests otherwise. Maybe others can comment.
You might like to look at how Boost.Container works. It should use allocator::pointer even on C++03.
Note that trying to use a smart pointer for allocator::pointer is unlikely to work in general, e.g. you can't use shared_ptr, because the semantics are not what the container expects. The most common use for redefining allocator::pointer that I've seen is to store offset in memory-mapped files and similar.
Thanks for your input... I am trying out boost::container::... right now and it is not a trivial task to use a smart pointers inside containers but I think it is possible.
I saw functions like to_raw_pointer() were user before calling the allocator's constructors & destructors... I believe this should be cleaned up sooner or later but for now I think I can survive by overloading only the allocate & deallocate functions.
I managed to make it compile with MSVC 2015 with a smart pointer inside containers: template <typename T, typename UserPool = system_pool<system_pool_tag, sizeof(char)> > class block_allocator { typedef T element_type; public: typedef element_type value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef block_ptr<element_type> pointer; typedef block_ptr<const element_type> const_pointer; typedef element_type & reference; typedef const element_type & const_reference; [...] My example block_ptr_test2.cpp doesn't work yet but at least I can go from here. That's the real stress test I was looking for.

On 2016-02-18 10:29 PM, Phil Bouchard wrote:
On 2016-02-18 7:09 PM, Phil Bouchard wrote:
On 02/18/2016 06:30 AM, Phil Endecott wrote:
Phil Bouchard wrote:
I think [std::list etc] should make use of the allocator's specific pointer
In C++03, containers were allowed to assume that allocator::pointer == value_type*. This is not true since C++11, where it should use allocator::pointer via allocator_traits.
A subtlety is that in the code you posted you're dealing with node pointers, not value_type pointers. I'm not sure what's going on there. My first thought was that you were looking at a pre-11 version of libstdc++, but I see a #if that suggests otherwise. Maybe others can comment.
You might like to look at how Boost.Container works. It should use allocator::pointer even on C++03.
Note that trying to use a smart pointer for allocator::pointer is unlikely to work in general, e.g. you can't use shared_ptr, because the semantics are not what the container expects. The most common use for redefining allocator::pointer that I've seen is to store offset in memory-mapped files and similar.
Thanks for your input... I am trying out boost::container::... right now and it is not a trivial task to use a smart pointers inside containers but I think it is possible.
I saw functions like to_raw_pointer() were user before calling the allocator's constructors & destructors... I believe this should be cleaned up sooner or later but for now I think I can survive by overloading only the allocate & deallocate functions.
I managed to make it compile with MSVC 2015 with a smart pointer inside containers:
template <typename T, typename UserPool = system_pool<system_pool_tag, sizeof(char)> > class block_allocator { typedef T element_type;
public: typedef element_type value_type; typedef size_t size_type; typedef ptrdiff_t difference_type; typedef block_ptr<element_type> pointer; typedef block_ptr<const element_type> const_pointer; typedef element_type & reference; typedef const element_type & const_reference; [...]
My example block_ptr_test2.cpp doesn't work yet but at least I can go from here. That's the real stress test I was looking for.
I have to admit MSVC 2015 got a clean STL... block_ptr_test2.cpp doesn't crash but some assertions are wrong. Is there any plans from Boost to make the Boost.Container work with inner smart pointers? I don't think there is any other alternative if people want to plugin memory management.
participants (3)
-
Phil Bouchard
-
Phil Bouchard
-
Phil Endecott