Should std::allocator::rebind be used with std::map?

Dear Boosters Some old implementations of std::allocator don't provide the rebind member template (e.g. MSVC6.0 stdlib). This keeps code as the following from compiling: typedef std::map< const state_base_type *, event_queue_type, std::less< const state_base_type * >, typename allocator_type::template rebind< // *** here *** std::pair< const state_base_type * const, event_queue_type >
::other > deferred_map_type;
However, this map will internally not allocate objects of the type std::pair< const state_base_type * const, event_queue_type > anyway but rather of some implementation-defined tree node type. So, the above typedef could also be written as follows, ... typedef std::map< const state_base_type *, event_queue_type, std::less< const state_base_type * >, allocator_type > deferred_map_type; which should work with just about any implementation of the std library, as long as the used container is a list, (multi)set or (multi)map. Now, the questions are: - Does the standard allow the second variant (I haven't found anything pro or contra)? - Even if the standard does not allow it or is silent on it, would anyone bother to write the technically more correct first variant? If yes, even at the expense of making the code compileable on fewer compilers (or having to clutter the code with more #ifdefs)? Thanks & Regards, Andreas

Hi Andreas Andreas Huber ha escrito:
Dear Boosters
Some old implementations of std::allocator don't provide the rebind member template (e.g. MSVC6.0 stdlib). This keeps code as the following from compiling:
typedef std::map< const state_base_type *, event_queue_type, std::less< const state_base_type * >, typename allocator_type::template rebind< // *** here *** std::pair< const state_base_type * const, event_queue_type >
::other > deferred_map_type;
However, this map will internally not allocate objects of the type std::pair< const state_base_type * const, event_queue_type > anyway but rather of some implementation-defined tree node type. So, the above typedef could also be written as follows, ...
typedef std::map< const state_base_type *, event_queue_type, std::less< const state_base_type * >, allocator_type > deferred_map_type;
which should work with just about any implementation of the std library, as long as the used container is a list, (multi)set or (multi)map.
Well, this is not generally true. In most cases the thing will work, but consider for example the following: #include <list> typedef std::list< int, std::allocator<double>
my_list;
int main() { my_list l; my_list::reference e=*l.begin(); //error here } This actually fails to compile in CW 9.3 (it works for some other environments). Strictly speaking, CW 9.3 is right to not compile the snippet, as my_list::reference is double& instead of int&. The fact that it compiles for other stdlibs is sheer luck.
Now, the questions are:
- Does the standard allow the second variant (I haven't found anything pro or contra)?
The std does not allow it. See 23.1.8: "[...] All other constructors for these container types take an Allocator& argument (lib.allocator.requirements), an allocator whose value type is the same as the container's value type.[...]"
- Even if the standard does not allow it or is silent on it, would anyone bother to write the technically more correct first variant? If yes, even at the expense of making the code compileable on fewer compilers (or having to clutter the code with more #ifdefs)?
The non-std variant can lead to actual errors (admittedly, the demo snippet is not so likely to occur in practice, but it is not unrealistic, think for example about a generic routine.) An alternative is to write an allocator adaption layer that takes care of the differences in rebinding support among different stdlibs. See for instance http://www.boost-consulting.com/boost/boost/multi_index/detail/allocator.hpp (rebind_to utility) for an example of what can be done to overcome the problem. Hope this helps, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Hello Joaquín,
which should work with just about any implementation of the std library, as long as the used container is a list, (multi)set or (multi)map.
Well, this is not generally true. In most cases the thing will work, but consider for example the following:
#include <list>
typedef std::list< int, std::allocator<double>
my_list;
int main() { my_list l; my_list::reference e=*l.begin(); //error here }
This actually fails to compile in CW 9.3 (it works for some other environments). Strictly speaking, CW 9.3 is right to not compile the snippet, as my_list::reference is double& instead of int&. The fact that it compiles for other stdlibs is sheer luck.
Ok, I missed this. I think your snippet should not compile on *any* std conforming implementation as the standard clearly says that the type of std::list< ..., Allocator >::reference must be equal to Allocator::reference. [snip]
http://www.boost-consulting.com/boost/boost/multi_index/detail/allocator.hpp
(rebind_to utility) for an example of what can be done to overcome the problem.
Hmmm, any chance this will make it into boost::detail namespace instead of boost::multi_index::detail, for V1.32? That'd be great because I could then reuse it in boost::fsm. I guess other libraries could benefit from this also.
Hope this helps,
Yes, very. Thanks! Regards, Andreas

Andreas Huber <ah2003 <at> gmx.net> writes:
http://www.boost-consulting.com/boost/boost/multi_index/detail/allocator.hpp
(rebind_to utility) for an example of what can be done to overcome the problem.
Hmmm, any chance this will make it into boost::detail namespace instead of boost::multi_index::detail, for V1.32? That'd be great because I could then reuse it in boost::fsm. I guess other libraries could benefit from this also.
Well, there's already a detail/allocator.hpp header by John Maddock! I had a cursory glance at it and seems like the functionality and workarounds provided there are not the same as mine --the header is not very self-explanatory. Maybe we can coalesce the two things together, but I'm not sure. John? Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

Hmmm, any chance this will make it into boost::detail namespace instead of boost::multi_index::detail, for V1.32? That'd be great because I could then reuse it in boost::fsm. I guess other libraries could benefit from this also.
Well, there's already a detail/allocator.hpp header by John Maddock! I had a cursory glance at it and seems like the functionality and workarounds provided there are not the same as mine --the header is not very self-explanatory. Maybe we can coalesce the two things together, but I'm not sure. John?
By all means, actually the current detail/allocator.hpp is designed for classes that are using an allocator internally, and may need to do a rebind internally; the workarounds in there probably won't work for std lib classes (or at least have never been tested with them). I also think that this header will become obsolete when the next regex revision becomes available, so basically do whatever you want with it, or I guess rename it for now until I can remove it entirely. John.

John Maddock <john <at> johnmaddock.co.uk> writes:
Hmmm, any chance this will make it into boost::detail namespace instead of boost::multi_index::detail, for V1.32? That'd be great because I could then reuse it in boost::fsm. I guess other libraries could benefit from this also.
Well, there's already a detail/allocator.hpp header by John Maddock!
[...]
By all means, actually the current detail/allocator.hpp is designed for classes that are using an allocator internally, and may need to do a rebind internally; the workarounds in there probably won't work for std lib classes (or at least have never been tested with them). I also think that this header will become obsolete when the next regex revision becomes available, so basically do whatever you want with it, or I guess rename it for now until I can remove it entirely.
Hi again. How am I supposed to rename your header? Will you take care of fixing the refs in your code? If so, do you propose some name for it until you finally remove it in next version of Boost.Regex? (BTW, I extensively grepped the CVS and seems that nobody except Boost.Regex is using this header, so the renaming should be harmless.) Thanx Joaquín M López Muñoz Telefónica, Investigación y Desarrollo

John Maddock ha escrito:
How am I supposed to rename your header? Will you take care of fixing the refs in your code? If so, do you propose some name for it until you finally remove it in next version of Boost.Regex?
OK I've moved it,
OK, thanks! I'll move my allocator.hpp there in the following days. Best, Joaquín M López Muñoz Telefónica, Investigación y Desarrollo
participants (4)
-
Andreas Huber
-
Joaquin M Lopez Munoz
-
Joaquín Mª López Muñoz
-
John Maddock