Topic: Replacing mbstate_t with pimpl


Author: David Krauss <potswa@gmail.com>
Date: Thu, 30 Sep 2010 01:57:02 CST
Raw View
One of the main reasons for slow adoption of custom codecvt facets is
the limited nature of std::mbstate_t. The type is entirely undefined
aside from being imported from the C library, which implies it is POD.
Therefore, user codecvts must be specializations, not derivations.
Specializing codecvt is unfortunately hard because the base template
is not required to be usable (perhaps forbidden from it), so there is
no base class to use except the nearly-empty codecvt_base.

There would be no problem if mbstate_t had been replaced by an opaque
container, for example std::vector<max_align_t>. Each codecvt could
initialize as much state storage as necessary, and streampos objects
(which contain mbstate_t) would copy the state on the heap as needed.
Although heap reallocations are expensive, so is copying the hefty
mbstate_t object, at least on Darwin where it is 128 bytes and *never
actually holds anything* as used by GNU libstdc++.

But these days, std::shared_ptr provides an even better solution. The
state may be not only kept on the heap, but also of polymorphic type
copied only on write. This makes it easy to create an entire hierarchy
of codecvts.

It's a pretty radical change, but for C++2x (or whatever the next
major revision is) I propose unhooking std::mbstate_t from
C ::mbstate_t and defining it to be std::shared_ptr< cvt_state_base >
as demonstrated in the code linked below. It seems to work pretty
well, but the fact of changing the char_traits arguments to everything
will always be a major hassle.

http://pastie.org/1188625

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]