http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55043

--- Comment #17 from Daniel Krügler <daniel.kruegler at googlemail dot com> 
2012-10-24 17:48:07 UTC ---
(In reply to comment #15)
> > 1) It will prevent the incomplete type support
> 
> Ouch... but not required by the standard.

I agree, but I consider that as a high price.

> > 2) The implementation changes are not small (my guess)
> 
> Apart from the changes to allocator_traits and defining CopyInsertable etc.
> (which I think isn't so hard, I can do that tonight) IIUC it would require
> changing every container so that e.g.
> 
>     vector<T,A>::vector(const vector&)
> 
> becomes
> 
>     template<typename U>
>       vector<T,A>::vector(const vector<U,A>&)
> 
> with constraints is_same<T,U> and CopyInsertable<A,T>, because we can't
> constrain that constructor if it's not a template
> 
> Is that even allowed under the as-if rule?

I don't think that this works. I can elaborate what I had in my mind when
comparing with optional, but I think this is not needed to solve the issue and
would lengthen here the discussion. Looking at the concrete problem here I
think the only thing that is needed is a conditional noexcept for all
containers move constructors (which is presumably a border-case for the allowed
extensions but to me an acceptable one. I tend to suggest to open an LWG issue
for this). Now I'm reading below that the move constructor always seems to need
to allocate memory, is that really true? IMO that is the actual problem here.

> Is there some other way to make examples like this compile?
> 
>   #include <vector>
> 
>   struct M
>   {
>     M() = default;
>     M(M&&) = default;
>     M& operator=(M&&) = default;
>   };
> 
>   typedef std::vector<M> S;
> 
>   static_assert( !std::is_copy_constructible<S>::value,
>                  "not CopyConstructible" );

This is possible with my more-constraining model in mind that would really
enforce that vectors value type is a complete type during instantiation of
vector. I do not suggest to follow this path, but if you really want to do
that, here the sketch (I can show you the complete code of my optional
implementation that does so, if you want): The basic idea is to ensure that
vector becomes conditionally derived from a base-class with a deleted
copy-constructor. An empty tagging class suffices, e.g.

template<>
struct ctor_base<member_policy::move | member_policy::copy>
{
  constexpr ctor_base() noexcept = default;
  ctor_base(const ctor_base& rhs) noexcept = default;
  ctor_base(ctor_base&& rhs) noexcept = default;
  ctor_base& operator=(const ctor_base&) noexcept = default;
  ctor_base& operator=(ctor_base&&) noexcept = default;
};

template<>
struct ctor_base<member_policy::move>
{
  constexpr ctor_base() noexcept = default;
  ctor_base(const ctor_base&) = delete;
  ctor_base(ctor_base&& rhs) noexcept = default;
  ctor_base& operator=(const ctor_base&) noexcept = default;
  ctor_base& operator=(ctor_base&&) noexcept = default;
};

The condition for the base class selection is the outcome of
std::is_copy_constructible<value_type>. This design has the effect that you can
delete-away the effective copy-constructor of the container, if the value type
is not copyable.

Reply via email to