Date: Sat, 25 Oct 2025 01:01:46 +0100
On Sat, 25 Oct 2025, 00:53 organicoman via Std-Proposals, <
std-proposals_at_[hidden]> wrote:
>
> Hello,
> Given a container C of value_type T, the expected behavior when applying
> an action on the container is to see that action distributed over its
> elements.
> -Copying the container->copies each elem.
> -Destroying the container->destroys each elem.
> -Moving the container-> moves each elem.
> (Moving here in the sense moving from one memory location to another one).
>
No, I don't expect that when moving a container. I expect the elements to
stay in exactly the same memory locations, and ownership of that memory to
be transferred.
By extrapolation:
> -Applying an action-> applys it on each elem.
> ...
> Yet there is one fundamental action that doesn't comply to this mental
> model:
> Assignment !
> When you assign one container to another, it is not guaranteed that all
> elements use Assignment operation.
> C<T> v1;
> v1 = v2; // or = std::move(v2);
> Usually the implementation distributes copy-construction, or
> move-construction operation on each element instead of copy/move assignment
> operator.
>
Again, not when moving (unless you use non-propagating allocators and
they're not equal).
And sometimes you see a mixture of both (construction and assignment)
> Let say you have:
>
>
> #include <vector>
> #include <iostream>
> struct A{
> A(){ std::puts(__PRETTY_FUNCTION__);}
> A(const A&)
> { std::puts(__PRETTY_FUNCTION__);}
> A(A&&)
> { std::puts(__PRETTY_FUNCTION__);}
> A& operator=(const A&) = default;//elete;
> A& operator=(A&&)= default;//elete;
> };
>
> int main()
> {
> std::vector<A> v1(5);
> std::vector<A> v2;
> std::puts("-----");
> v2 = v1;
> return 0;
> }
> ######
>
> Output:
>
> A::A()
> A::A()
> A::A()
> A::A()
> A::A()
> -----
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
>
>
>
> As you can see...
> The mental model of distributing actions over each element is not
> respected for the copy assignment operation, instead of no log after the
> "-----" above, we see "A::A(const A&)".
>
> T*he proposal*:
> To keep the mental model of "action distribution over container
> elements", i suggest adding the capability of "construction by assignment"
> That is, we can construct an object directly by copy assignment or move
> assignment.
>
> And the following snippet should not be UB.
> ///
> T* p = (T*)malloc(sizeof(T));
> T val;
> *p = val; // UB here
> ///
> for all T's either trivial or non trivial constructible.
>
> One suggestion is to add 2 new special functions
>
> T& operator = (std::construct_tag, const T&);
> T& operator = (std::construct_tag, T&&);
>
> Where the implementation just delegates the construction to the
> appropriate copy/move constructor. Expl
> T& operator = (std::construct_tag, const T& t)
> : T(t)
> { }
>
> T& operator = (std::construct_tag, T&& t)
> : T(std::move(t))
> { }
>
> The only problemt is : how to detect that the object is being constructed
> by assignment i.e how to choose one of the above new special functions?
> I mean:
> ///
> T t1, t2;
> T* p;
> T* q = &t1;
> *p = t2; // must pick construct by copy assign
> *q = t2; // must pick regular copy assign
> ///
>
> Over to you.
>
Why?
Your mental model is not how it works, why would we complicate things to
support an incorrect model?
> Thanks
> Sent from my Galaxy
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
std-proposals_at_[hidden]> wrote:
>
> Hello,
> Given a container C of value_type T, the expected behavior when applying
> an action on the container is to see that action distributed over its
> elements.
> -Copying the container->copies each elem.
> -Destroying the container->destroys each elem.
> -Moving the container-> moves each elem.
> (Moving here in the sense moving from one memory location to another one).
>
No, I don't expect that when moving a container. I expect the elements to
stay in exactly the same memory locations, and ownership of that memory to
be transferred.
By extrapolation:
> -Applying an action-> applys it on each elem.
> ...
> Yet there is one fundamental action that doesn't comply to this mental
> model:
> Assignment !
> When you assign one container to another, it is not guaranteed that all
> elements use Assignment operation.
> C<T> v1;
> v1 = v2; // or = std::move(v2);
> Usually the implementation distributes copy-construction, or
> move-construction operation on each element instead of copy/move assignment
> operator.
>
Again, not when moving (unless you use non-propagating allocators and
they're not equal).
And sometimes you see a mixture of both (construction and assignment)
> Let say you have:
>
>
> #include <vector>
> #include <iostream>
> struct A{
> A(){ std::puts(__PRETTY_FUNCTION__);}
> A(const A&)
> { std::puts(__PRETTY_FUNCTION__);}
> A(A&&)
> { std::puts(__PRETTY_FUNCTION__);}
> A& operator=(const A&) = default;//elete;
> A& operator=(A&&)= default;//elete;
> };
>
> int main()
> {
> std::vector<A> v1(5);
> std::vector<A> v2;
> std::puts("-----");
> v2 = v1;
> return 0;
> }
> ######
>
> Output:
>
> A::A()
> A::A()
> A::A()
> A::A()
> A::A()
> -----
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
> A::A(const A&)
>
>
>
> As you can see...
> The mental model of distributing actions over each element is not
> respected for the copy assignment operation, instead of no log after the
> "-----" above, we see "A::A(const A&)".
>
> T*he proposal*:
> To keep the mental model of "action distribution over container
> elements", i suggest adding the capability of "construction by assignment"
> That is, we can construct an object directly by copy assignment or move
> assignment.
>
> And the following snippet should not be UB.
> ///
> T* p = (T*)malloc(sizeof(T));
> T val;
> *p = val; // UB here
> ///
> for all T's either trivial or non trivial constructible.
>
> One suggestion is to add 2 new special functions
>
> T& operator = (std::construct_tag, const T&);
> T& operator = (std::construct_tag, T&&);
>
> Where the implementation just delegates the construction to the
> appropriate copy/move constructor. Expl
> T& operator = (std::construct_tag, const T& t)
> : T(t)
> { }
>
> T& operator = (std::construct_tag, T&& t)
> : T(std::move(t))
> { }
>
> The only problemt is : how to detect that the object is being constructed
> by assignment i.e how to choose one of the above new special functions?
> I mean:
> ///
> T t1, t2;
> T* p;
> T* q = &t1;
> *p = t2; // must pick construct by copy assign
> *q = t2; // must pick regular copy assign
> ///
>
> Over to you.
>
Why?
Your mental model is not how it works, why would we complicate things to
support an incorrect model?
> Thanks
> Sent from my Galaxy
>
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>
Received on 2025-10-25 00:02:02
