Boost logo

Boost :

From: Howard Hinnant (howard.hinnant_at_[hidden])
Date: 2006-03-13 10:40:26


On Mar 13, 2006, at 8:42 AM, Vaclav Vesely wrote:

> Hi,
>
> draft of the is_movable trait is attached.
>
> Notes:
>
> - Implicit implementation is based on the has_trivial_copy trait.
>
> - For STL configurations, which defines BOOST_HAS_MOVABLE_STL,
> is_movable.hpp declares STL containers (and their const versions)
> as movable. Partial template specialization is required (!defined
> (BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)).
>
>
> Open issues:
>
> - I'm not sure with volatiles. has_trivial_copy declares volatile
> types explicitly as not has_trivial_copy. I don't know why but
> is_movable should probably follow this.
>
> - I have tested MSVC (6, 7.1 and 8) and GCC (3.2.3 - MinGW)
> compilers. MSVC is fine but GCC complains with specializations for
> STL types. It seems to be related to a different macro expansion
> strategy of preprocessor. I'm not able to use BOOST_PP_COMMA macro
> correctly. I will appreciate any help.

"is_movable" is an overly vague name for what you're attempting to
detect.

Given a type T, a non-initialized x, and an initialized y, here is
the sequence of statements you're optimizing.

::new(&x) T(move(y));
y.~T();

In the current nomenclature (the move proposal before the committee),
there are terms such as "move constructor" and "move assignment". In
both of these cases the source is left in a constructed state. It
would be very easy to confuse the meaning of "is_movable" with these
existing definitions.

I don't know what a good name would be, but I tend to think that the
following would be getting closer:

has_trivial_move_constructor_destructor

or:

has_trivial_destructive_move_constructor

BOOST_HAS_MOVABLE_STL seems overly simplistic, and perhaps even
dangerous.

Overly simplistic in that for some implementations (e.g. gcc 4.x)
some of the containers will have a trivial destructive move
constructor and some containers won't. Additionally, for containers
that store an Allocator, Comparator, or other policy class, their
eligibility (if potentially eligible in the first place), should
depend upon the eligibility of the Allocator and/or Comparator (and
because of this std::comparators need to be treated - std::less,
etc.). And in at least one implementation I'm aware of, eligibility
for even something as simple as vector<char> depends on whether
you're using the debugging version of the STL. In the debugging
version the vector holds a list of outstanding iterators which in
turn point back to the vector, making it ineligible.

The last point highlights the danger aspect. As currently set up,
you can silently get a false positive for eligibility just by
switching into debug mode (on at least one implementation). The
other danger is that vendors have been known to change the
eligibility of some containers from release to release (examples
include gcc node-based containers). Since this trait can't be auto-
detected for things as complicated as containers, I recommend the
trait only be turned on for specific version numbers of a std::lib,
and that a true response not be forward compatible (later versions
need to be specifically set to true).

If this trait is to exist, you can't go wrong with including pair,
and perhaps even tuple. At the very least their implementation is
entertaining (at least tuple's). :-)

-Howard


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk