Using allocator rebind on an incomplete type

In trying to clean up some code in Boost.Pool, I've run afoul of some code in Microsoft's implementation of the STL where they are using allocator::rebind on an incomplete type. Something like this: struct Node; // Incomplete! template<typename T, typename Alloc> struct List { Alloc<T>::rebind<Node>::other::pointer node_p; ... } I believe that attempting to instantiate an allocator with an incomplete type is illegal so, by extension, I would have assumed that attempting to rebind on an incomplete type would also be illegal, no? -Chris

on Thu Oct 23 2008, Chris Newbold <Chris.Newbold-AT-mathworks.com> wrote:
In trying to clean up some code in Boost.Pool, I've run afoul of some code in Microsoft's implementation of the STL where they are using allocator::rebind on an incomplete type. Something like this:
struct Node; // Incomplete!
template<typename T, typename Alloc> struct List { Alloc<T>::rebind<Node>::other::pointer node_p; ... }
I believe that attempting to instantiate an allocator with an incomplete type is illegal
Attempting to instantiate any library-defined template on an incomplete type (I think shared_ptr is the one exception to this rule now) induces undefined behavior. Thus, std::allocator<T>::rebind<X> on an incomplete X induces undefined behavior when a user does it. The library might know enough about std::allocator to do it anyway, though. It doesn't mean that instantiating any old template whose instances model Allocator on an incomplete type is illegal, though.
so, by extension, I would have assumed that attempting to rebind on an incomplete type would also be illegal, no?
I don't think that's strictly illegal -- at least not by the rule you are alluding to. It depends on what the Allocator requirements say. -- Dave Abrahams BoostPro Computing http://www.boostpro.com

From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams Sent: Thursday, October 23, 2008 7:16 PM
Thus, std::allocator<T>::rebind<X> on an incomplete X induces undefined behavior when a user does it. The library might know enough about std::allocator to do it anyway, though.
Microsoft's std::list implementation uses rebind on the (user-supplied) allocator to get an allocator for its internal linked-list node. However, at the time it applies rebind, the linked-list node structure is incomplete. In this case they cannot assume the allocator is std::allocator-- in effect, they've imposed a constraint that user-defined allocators "work" for incomplete types. -Chris

Chris Newbold wrote:
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of David Abrahams Sent: Thursday, October 23, 2008 7:16 PM
Thus, std::allocator<T>::rebind<X> on an incomplete X induces undefined behavior when a user does it. The library might know enough about std::allocator to do it anyway, though.
Microsoft's std::list implementation uses rebind on the (user-supplied) allocator to get an allocator for its internal linked-list node. However, at the time it applies rebind, the linked-list node structure is incomplete. In this case they cannot assume the allocator is std::allocator-- in effect, they've imposed a constraint that user-defined allocators "work" for incomplete types.
Yes, but their other choice is to use a Node* as the link between the list nodes. That imposes a different set of constraints on user defined allocators. Which set do we prefer? Bo Persson

From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bo Persson Sent: Saturday, October 25, 2008 8:13 AM
Yes, but their other choice is to use a Node* as the link between the list nodes. That imposes a different set of constraints on user defined allocators.
The libstdc++ list implementation does not appear to impose the incomplete type constraint on allocators. I realize that there is practically nothing that I can do about the constraints that Microsoft's list is imposing, but I did want to get a feel for whether the constraint on incomplete types is something that I should expect or whether I should just implement a Microsoft-specific workaround for the case I've run into... -Chris

Chris Newbold wrote:
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bo Persson Sent: Saturday, October 25, 2008 8:13 AM
Yes, but their other choice is to use a Node* as the link between the list nodes. That imposes a different set of constraints on user defined allocators.
The libstdc++ list implementation does not appear to impose the incomplete type constraint on allocators.
No, but they impose the constraint that allocator<T>::pointer must be T*. This is allowed by the (current) standard, but it also recommends implementations to not have this restriction.
I realize that there is practically nothing that I can do about the constraints that Microsoft's list is imposing, but I did want to get a feel for whether the constraint on incomplete types is something that I should expect or whether I should just implement a Microsoft-specific workaround for the case I've run into...
It is a different set of constraints. You choose what is "normal" and what needs a "workaround"... Bo Persson

on Mon Oct 27 2008, Chris Newbold <Chris.Newbold-AT-mathworks.com> wrote:
From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Bo Persson Sent: Saturday, October 25, 2008 8:13 AM
Yes, but their other choice is to use a Node* as the link between the list nodes. That imposes a different set of constraints on user defined allocators.
The libstdc++ list implementation does not appear to impose the incomplete type constraint on allocators.
I realize that there is practically nothing that I can do about the constraints that Microsoft's list is imposing, but I did want to get a feel for whether the constraint on incomplete types is something that I should expect or whether I should just implement a Microsoft-specific workaround for the case I've run into...
Hi Chris, If you want to write portable code, you should expect any constraints that the standard allows the library to impose. A particular library implementation may choose to impose fewer constraints, of course. That appears to be the case for libstdc++, but that doesn't mean you should count on it. -- Dave Abrahams BoostPro Computing http://www.boostpro.com
participants (3)
-
Bo Persson
-
Chris Newbold
-
David Abrahams