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).
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.
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&)".The 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 functionsT& 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. ExplT& 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.
--ThanksSent from my Galaxy
Std-Proposals mailing list
Std-Proposals@lists.isocpp.org
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals