What exactly is a const variable? - c++

I understand const pointers. However I don't entirely understand const normal variables.
const int a
The statement above I understand because it's a primitive. So it can only mean one thing: the value of a cannot be changed.
But whag about this one?
const Car car
This could mean one of two things:
A- The value of variable car can't be changed. I.e., I can't put inside it a different Car.
B- The object itself that this variable holds cannot be changed. I.e., we can't change the state of the object that's inside this variable.
Which one of these is correct?

Both.
Since The value of variable car and the state of the object that's inside this variable are the same thing.
An objects is nothing more than the aggregation of its members.

Both are correct:
A- The value of variable car can't be changed. I.e., I can't put inside it a different Car.
you will not be able to assign to car any other Car class instances. If you are using java, then this is not the same as assigning reference to new variable, in c++ whole object is copied in this case.
B- The object itself that this variable holds cannot be changed. I.e., we can't change the state of the object that's inside this variable.
its correct because you will only be able to call const methods which are also not allowed to modify fields, unless they are marked as mutable.

This isn't an entirely straightforward question. Specifically, making car const makes the compiler treat all of car's non-mutable members as const. It also prevents you from calling non-const member functions on car.
What does treating a member as const mean? Well, it depends on its type. If it's a pointer, it's the pointer and not the pointee that is treated as const. Say we have the following class:
class C
{
public:
Foo foo;
Bar *bar;
mutable Baz baz;
void nc()
{
foo = ...; // fine
bar = ...; // fine
*bar = ...; // fine
baz = ...; // fine
}
void c() const
{
foo = ...; // not fine
bar = ...; // not fine
*bar = ...; // fine
baz = ...; // fine
}
};
const C c;
c.foo = ...; // not fine
c.bar = ...; // not fine
*c.bar = ...; // fine
c.baz = ...; // fine
c.nc(); // not fine
c.c(); // fine
If you had a const instance of C, you would be able to call const member functions on it. You (depending on access) or those const member functions would also be able to change the thing pointed to by bar and the actual object baz, but not foo or bar, since the compiler would treat foo as being of type const Foo, bar as being of type Bar *const and baz as being of type Baz.
To directly address your question, both A and B are roughly correct views of what's going on, but neither captures the true situation well enough to be an answer to the question.
In particular, A (which essentially says you can't assign to const objects) is a simplification, since it's possible (maybe unwise, but possible) to write an assignment operator that only assigns to mutable members or to pointees.
B is a simplification because it doesn't take into account the possible presence of mutable members inside your class. Depending on what you mean by 'state', it's closer to the truth, since mutable members are often used as part of the private implementation and don't represent part of the class's logical state, but it's still not really accurate.

Both are true. Assigning a new Car to car is done by invoking Car::operator=(Car const& other), whether explicitly implemented or compiler-generated. That, in turn, assigns all of the members of car from those of other. So assignment is state-changing.
From the confusion, I wonder if you're more used to a language like C# or Java which has reference-typed object variables instead of object-typed variables. There (like with pointers in C++), assigning to a variable is different from changing its state, because the original Car stored in car would still be out there somewhere, unchanged. But with value-typed object variables, you're not really putting "a different Car inside it" -- you're changing the original Car so that it looks the same as the new Car.

Related

How do constant references work?

Recently I have been learning about good programming practice in C++ and found out that many programs pass objects to functions by reference so that multiple instances are not created. I have also learned that passing a constant reference prevents the original object from being modified however I do not understand how this works exactly. Shouldn't a constant reference create a new instance because the original object cannot be modified through the reference but the reference can still be used like a separate object? I'm fairly certain that this is not how it works but then, how does it work? Is there something I missed?
I have also learned that passing a constant reference prevents the original object from being modified [...]
Not quite. You are not allowed to modify the object through the const &. In other words, you have read-only access. But nothing natively prevents other code with read-write access (for example the original owner of the referred object) to modify it. You do need to be careful when designing so that such changes do not surprise you.
A constant reference (const&) is similar to a pointer to a constant object. You are allowed to read it through the reference but not modify it. Others, holding a non-const reference can still modify it.
Shouldn't a constant reference create a new instance because the
original object cannot be modified through the reference but the
reference can still be used like a separate object?
It's better to call it a reference to a constant object. This makes it much clearer how the thing works. Calling it the other way around is just confusing because any reference is constant (meaning you can't let it refer to another object after initialization).
So a reference to a constant object is just an additional name for an existing object (like a non-const reference) with the restriction that this name only allows reading from the existing object.
This means that through a reference to a constant object you can:
only read from member variables of the object, but not assign to them, unless a member is marked as mutable
only call methods of the object that are marked as const
Example:
struct Foo
{
int a;
mutable int b;
void SetA( int newA ) { a = newA; }
int GetA() const { return a; }
};
void DoSomething( const Foo& f )
{
// Here, f is just another name for foo, but it imposes some restrictions:
f.a = 42; // compiler error, can't modify member!
f.SetA( 42 ); // compiler error, can't call non-const method!
int x = f.a; // OK, reading is allowed.
f.b = 42; // OK, because b is marked as mutable
int y = f.GetA(); // OK, because GetA() is marked as const
}
int main()
{
Foo foo;
DoSomething( foo );
}

why use a const non-reference when const reference lifetime is the length of the current scope

So in c++ if you assign the return value of a function to a const reference then the lifetime of that return value will be the scope of that reference. E.g.
MyClass GetMyClass()
{
return MyClass("some constructor");
}
void OtherFunction()
{
const MyClass& myClass = GetMyClass(); // lifetime of return value is until the end
// of scope due to magic const reference
doStuff(myClass);
doMoreStuff(myClass);
}//myClass is destructed
So it seems that wherever you would normally assign the return value from a function to a const object you could instead assign to a const reference. Is there ever a case in a function where you would want to not use a reference in the assignment and instead use a object? Why would you ever want to write the line:
const MyClass myClass = GetMyClass();
Edit: my question has confused a couple people so I have added a definition of the GetMyClass function
Edit 2: please don't try and answer the question if you haven't read this:
http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
If the function returns an object (rather than a reference), making a copy in the calling function is necessary [although optimisation steps may be taken that means that the object is written directly into the resulting storage where the copy would end up, according to the "as-if" principle].
In the sample code const MyClass myClass = GetMyClass(); this "copy" object is named myclass, rather than a temporary object that exists, but isn't named (or visible unless you look at the machine-code). In other words, whether you declare a variable for it, or not, there will be a MyClass object inside the function calling GetMyClass - it's just a matter of whether you make it visible or not.
Edit2:
The const reference solution will appear similar (not identical, and this really just written to explain what I mean, you can't actually do this):
MyClass __noname__ = GetMyClass();
const MyClass &myclass = __noname__;
It's just that the compiler generates the __noname__ variable behind the scenes, without actually telling you about it.
By making a const MyClass myclass the object is made visible and it's clear what is going on (and that the GetMyClass is returning a COPY of an object, not a reference to some already existing object).
On the other hand, if GetMyClass does indeed return a reference, then it is certainly the correct thing to do.
IN some compilers, using a reference may even add an extra memory read when the object is being used, since the reference "is a pointer" [yes, I know, the standard doesn't say that, but please before complaining, do me a favour and show me a compiler that DOESN'T implement references as pointers with extra sugar to make them taste sweeter], so to use a reference, the compiler should read the reference value (the pointer to the object) and then read the value inside the object from that pointer. In the case of the non-reference, the object itself is "known" to the compiler as a direct object, not a reference, saving that extra read. Sure, most compilers will optimise such an extra reference away MOST of the time, but it can't always do that.
One reason would be that the reference may confuse other readers of your code. Not everybody is aware of the fact that the lifetime of the object is extended to the scope of the reference.
The semantics of:
MyClass const& var = GetMyClass();
and
MyClass const var = GetMyClass();
are very different. Generally speaking, you would only use the
first when the function itself returns a reference (and is
required to return a reference by its very semantics). And you
know that you need to pay attention to the lifetime of the
object (which is not under your control). You use the second
when you want to own (a copy of) the object. Using the second
in this case is misleading, can lead to surprises (if the
function also returns a reference to an object which is
destructed earlier) and is probably slightly less efficient
(although in practice, I would expect both to generate exactly
the same code if GetMYClass returns by value).
Performance
As most current compilers elide copies (and moves), both version should have about the same efficiency:
const MyClass& rMyClass = GetMyClass();
const MyClass oMyClass = GetMyClass();
In the second case, either a copy or move is required semantically, but it can be elided per [class.copy]/31. A slight difference is that the first one works for non-copyable non-movable types.
It has been pointed out by Mats Petersson and James Kanze that accessing the reference might be slower for some compilers.
Lifetime
References should be valid during their entire scope just like objects with automatic storage are. This "should" of course is meant to be enforced by the programmer. So for the reader IMO there's no differences in the lifetimes implied by them. Although, if there was a bug, I'd probably look for dangling references (not trusting the original code / the lifetime claim for the reference).
In the case GetMyClass could ever be changed (reasonably) to return a reference, you'd have to make sure the lifetime of that object is sufficient, e.g.
SomeClass* p = /* ... */;
void some_function(const MyClass& a)
{
/* much code with many side-effects */
delete p;
a.do_something(); // oops!
}
const MyClass& r = p->get_reference();
some_function(r);
Ownership
A variable directly naming an object like const MyClass oMyClass; clearly states I own this object. Consider mutable members: if you change them later, it's not immediately clear to the reader that's ok (for all changes) if it has been declared as a reference.
Additionally, for a reference, it's not obvious that the object its referring to does not change. A const reference only implies that you won't change the object, not that nobody will change the object(*). A programmer would have to know that this reference is the only way of referring to that object, by looking up the definition of that variable.
(*) Disclaimer: try to avoid unapparent side effects
I don't understand what you want to achieve. The reason that T const& can be bound (on the stack) to a T (by value) which is returned from a function is to make it possible other function can take this temporary as an T const& argument. This prevents you from requirement to create overloads. But the returned value has to be constructed anyway.
But today (with C++11) you can use const auto myClass = GetMyClass();.
Edit:
As an excample of what can happen I will present something:
MyClass version_a();
MyClass const& version_b();
const MyClass var1 =version_a();
const MyClass var2 =version_b();
const MyClass var3&=version_a();
const MyClass var4&=version_b();
const auto var5 =version_a();
const auto var6 =version_b();
var1 is initialised with the result of version_a()
var2 is initialised with a copy of the object to which the reference returned by version_b() belongs
var3 holds a const reference to to the temoprary which is returned and extends its lifetime
var4 is initialised with the reference returned from version_b()
var5 same as var1
var6 same as var4
They are semanticall all different. var3 works for the reason I gave above. Only var5 and var6 store automatically what is returned.
there is a major implication regarding the destructor actually being called. Check Gotw88, Q3 and A3. I put everything in a small test program (Visual-C++, so forgive the stdafx.h)
// Gotw88.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <iostream>
class A
{
protected:
bool m_destroyed;
public:
A() : m_destroyed(false) {}
~A()
{
if (!m_destroyed)
{
std::cout<<"A destroyed"<<std::endl;
m_destroyed=true;
}
}
};
class B : public A
{
public:
~B()
{
if (!m_destroyed)
{
std::cout<<"B destroyed"<<std::endl;
m_destroyed=true;
}
}
};
B CreateB()
{
return B();
}
int _tmain(int argc, _TCHAR* argv[])
{
std::cout<<"Reference"<<std::endl;
{
const A& tmpRef = CreateB();
}
std::cout<<"Value"<<std::endl;
{
A tmpVal = CreateB();
}
return 0;
}
The output of this little program is the following:
Reference
B destroyed
Value
B destroyed
A destroyed
Here a small explanation for the setup. B is derived from A, but both have no virtual destructor (I know this is a WTF, but here it's important). CreateB() returns B by value. Main now calls CreateB and first stores the result of this call in a const reference of type A. Then CreateB is called and the result is stored in a value of type A.
The result is interesting. First - if you store by reference, the correct destructor is called (B), if you store by value, the wrong one is called. Second - if you store in a reference, the destructor is called only once, this means there is only one object. By value results in 2 calls (to different destructors), which means there are 2 objects.
My advice - use the const reference. At least on Visual C++ it results in less copying. If you are unsure about your compiler, use and adapt this test program to check the compiler. How to adapt? Add copy / move constructor and copy-assignment operator.
I quickly added copy & assignment operators for class A & B
A(const A& rhs)
{
std::cout<<"A copy constructed"<<std::endl;
}
A& operator=(const A& rhs)
{
std::cout<<"A copy assigned"<<std::endl;
}
(same for B, just replace every capital A with B)
this results in the following output:
Reference
A constructed
B constructed
B destroyed
Value
A constructed
B constructed
A copy constructed
B destroyed
A destroyed
This confirms the results from above (please note, the A constructed results from B being constructed as B is derived from A and thus As constructor is called whenever Bs constructor is called).
Additional tests: Visual C++ accepts also the non-const reference with the same result (in this example) as the const reference. Additionally, if you use auto as type, the correct destructor is called (of course) and the return value optimization kicks in and in the end it's the same result as the const reference (but of course, auto has type B and not A).

writing `operator=` for non-static reference member class

#include <iostream>
class Bar
{
protected:
public:
int & x;
Bar(int & new_x)
:x(new_x)
{}
Bar & operator = (const Bar toCopy)
{
x = toCopy.x;
return *this;
}
};
int main()
{
int x1(1);
int x2(2);
Bar bar = Bar(x1);
std::cout << bar.x << std::endl;
bar = Bar(x2);
std::cout << bar.x << std::endl;
bar.x = 5;
std::cout << bar.x << std::endl;
std::cout << x1 << std::endl;
std::cout << x2 << std::endl;
}
The output is:
1
2
5
5
2
What I am trying to do is copy x and save it within the object bar.
The output suggests to me that the assignment operator has not done its magic, both in terms of copying and taking the value of the new object. I have followed this link.
Changing x into a value rather than a reference is not possible, as in the real program x is an abstract class.
Please if possible abstain from using heap assignment.
EDIT:
1. I realized that I have just butchered the C++ language. I would like to apologize to all "C++ian" speaking computers. My motivation was to assign a member abstract variable on the stack. As far as I understand, it cannot be done on the stack, because the size of the derived class is not known at compile time.
2. OK... I am a total n00b...(no sh*t, Sherlock!). "Effective C++ programming" #rhalbersma is a must have. It contains essentials, yet you wont find them anywhere (copy constructions, copy initializer),.. in one place anyway.
References can be confusing. So can const pointers. I'll try to clear things up by talking about both of them at the same time. What can I say, I'm an optimist.
First, const pointers.
We'll start with a class called Foo. We can have a pointer to this class -- a Foo*. We can have a pointer to a const instance of this class -- a Foo const*. And we can have a const pointer to a non-const instance of this class -- a Foo*const.
A Foo const* is a pointer you can change to data you cannot change.
A Foo*const is a pointer you cannot change to data you can change.
I'll assume you got that. I am, after all, an optimist. Next, lets look at references.
While it is true that references are aliases, sometimes it helps to think about them in a world where things have concrete implementations in terms of other types.
A Foo& is analogous to a Foo*const -- a non-changeable "pointer" to an instance of Foo you can change. So the Foo you are talking about is always the same one, but you can change its state.
Now, it is a bit more than that. There is some syntactic sugar. When you create a reference to another variable, it does the & automatically -- so when you do a Foo& f = a;, this is analogous to Foo*const f = &a;.
Second, when you use ., it does the same as -> in the pointer case. (And similarly for (most?) other operators)
Third, when you do assignment, it clearly cannot change the pointer's value -- because it is const -- but instead it changes the value of the thing pointed to. So Foo& f = a; a = b; does the equivalent of Foo*const f = &a; *f = b;.
It assigns the thing pointed to, rather than the pointer, when you use operator=. But when you initialize it, it doesn't use operator=, even if you have a = token.
Initialization is not the same as assignment in general, and the semantics of what happens with a & reference and a * pointer in initialization and assignment are very different.
Foo& f = a; f = b; does two completely different things. Initialization of a reference initializes the "const pointer" portion -- assignment to a reference modifies the thing pointed to.
My personal name for how initialization and assignment mean different things with references is "reference semantics", as opposed to "pointer semantics" where both initialization and assignment change what thing is being pointed to. In "reference semantics", initialization picks what thing is being pointed to, and assignment changes the state of the thing that is pointed to.
This is highly confusing, and I hope I helped make it confusing in a different way.
Bar bar = Bar(x1); is not assignment, but copy-initialization. It calls the copy constructor, not the copy assignment operator.
The problem though is that you don't understand reference - the member Bar::x is just an alias for another variable. Assigning something to it will also modify the original one.
The x inside bar is the same variable as the one called "x1" in main.
That's what references do - they take a variable and give it another name that you can use to refer to it.
Whatever you do to that variable under this new name is the same as doing it under any other name.
First, after
Bar bar = Bar(x1);
(which is copy initialization, not assignment)
"bar.x" refers to the same variable as the "x" inside the anonymous object on the right hand side, which in turn is a different name for "x1" in main.
After this, the name "bar.x" refers to the same variable as the name "x1".
The line
bar = Bar(x2);
assigns the value (i.e., 2) of the anonymous object's x, which is the same variable as x2, to the variable that is called "x" inside bar, but whose name is "x1" in main.
The line
bar.x = 5;
then assigns the value 5 to the variable whose name is "bar.x" which, again, is the same variable as "x1" in main.
You cannot make it refer to a different variable.
If you want something that can refer to different variables, you must use a pointer.

C++: Will structs be copied implicitly

I'm relatively new to C++ and I'm wondering if structs are copied in the following case:
struct foo {
int i;
std::vector<int> bar;
}
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
void main() {
Foobar foobar;
{
foo f;
f.i = 1;
f.bar.insert(2);
foobar.store(f);
}
// will a copy of f still exist in foobar.m_foo, or am I storing a NULL-Pointer at this point?
}
The reason why I am asking this is that I am originally a .NET developer and in .NET structures will be copied if you pass them to a function (and classes are not).
I'm pretty sure it would be copied if store was not declared to take f by reference, but I cannot change this code.
Edit: Updated the code, because I didn't know that the vector.insert would affect my question. In my case I store the struct as a member in a class, not a vector.
So my question really was: will f be copied at this->m_foo = f;?
Short answer: Yes.
Long answer: You'd have to get a pointer to a stack allocated struct and then let that struct go out of scope in order to end up with a dangling reference in your vector... but even then, you wouldn't have stored a NULL. C and C++ pointers are simple things, and will continue to point at a memory location long after that memory location has become invalid, if your code doesn't overwrite them.
It might also be worth noting that std::vector has a decent set of copy and move functions associated with it that will be called implicitly in this case, so the bar vector inside the struct will also be copied along with the simple integer i. Standard library classes tend to be quite well written, but code by other folk has no such guarantee!
Now, as regards your edit:
class Foobar {
foo m_foo;
void store(foo& f) {
this->m_foo = f;
}
}
You will still not have any problems with the foo instance stored in m_foo. This is because this->m_foo = f invokes a copying operation, as m_foo is not a variable of a reference or pointer type. If you had this instead: foo& m_foo then you would run into difficulties because instead of copying a foo instance you are instead copying a reference to a foo instance, and when that instance goes out of scope, the reference is no longer valid.
Yes, the struct will be copied, in the following function:
foos.insert(f);
As a copy is made, you won't be storing a null pointer / null reference.
However, like you've said, it won't be copied when you call store(f); as the function accepts the argument as a reference.
Your edit will still make a copy of Foo. You are assigning one instance of a variable to another instance of a variable. What you aren't doing is assigning one pointer (reference in C#) to another. You could probably do with doing some reading around C++ object instances, pointers, and references.
A copy of f is made during foos.insert(f)
void store(foo& f) {
foos.insert(f);
}
void main() {
{
foo f;
f.i = 1;
f.bar.insert(2);
store(f);
}
// at this place, local variable `f` runs out of scope, it's destroyed and cleaned up
// foos is holding the copy of `f`
}

Using a class with const data members in a vector

Given a class like this:
class Foo
{
const int a;
};
Is it possible to put that class in a vector? When I try, my compiler tells me it can't use the default assignment operator. I try to write my own, but googling around tells me that it's impossible to write an assignment operator for a class with const data members. One post I found said that "if you made [the data member] const that means you don't want assignment to happen in the first place." This makes sense. I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
I've written a class with const data members, and I never intended on using assignment on it, but apparently I need assignment to put it in a vector. Is there a way around this that still preserves const-correctness?
You have to ask whether the following constraint still holds
a = b;
/* a is now equivalent to b */
If this constraint is not true for a and b being of type Foo (you have to define the semantics of what "equivalent" means!), then you just cannot put Foo into a Standard container. For example, auto_ptr cannot be put into Standard containers because it violates that requirement.
If you can say about your type that it satisfies this constraint (for example if the const member does not in any way participate to the value of your object, but then consider making it a static data member anyway), then you can write your own assignment operator
class Foo
{
const int a;
public:
Foo &operator=(Foo const& f) {
/* don't assign to "a" */
return *this;
}
};
But think twice!. To me, it looks like that your type does not satisfy the constraint!
Use a vector of pointers std::vector<Foo *>. If you want to avoid the hassle of cleaning up after yourself, use boost::ptr_vector.
Edit: My initial stab during my coffee break, static const int a; won't work for the use case the OP has in mind, which the initial comments confirm, so I'm rewriting and expanding my answer.
Most of the time, when I want to make an element of a class constant, it's a constant whose value is constant for all time and across all instances of the class. In that case, I use a static const variable:
class Foo
{
public:
static const int a;
};
Those don't need to be copied among instances, so if it applied, that would fix your assignment problem. Unfortunately, the OP has indicated that this won't work for the case the OP has in mind.
If you want to create a read-only value that clients can't modify, you can make it a private member variable and only expose it via a const getter method, as another post on this thread indicates:
class Foo
{
public:
int get_a() const { return a; }
private:
int a;
};
The difference between this and
class Foo
{
public:
const int a;
};
is:
The const int gives you assurance that not even the implementation of the class will be able to muck with the value of a during the lifetime of the object. This means that assignment rightfully won't work, since that would be trying to modify the value of a after the object's been created. (This is why, btw, writing a custom operator=() that skips the copy of a is probably a bad idea design-wise.)
The access is different – you have to go through a getter rather than accessing the member directly.
In practice, when choosing between the two, I use read-only members. Doing so probably means you'll be able to replace the value of an object with the value of another object without violating semantics at all. Let's see how it would work in your case.
Consider your Grid object, with a width and height. When you initially create the vector, and let's say you reserve some initial space using vector::reserve(), your vector will be populated with initial default-initialized (i.e. empty) Grids. When you go to assign to a particular position in the vector, or push a Grid onto the end of the vector, you replace the value of the object at that position with a Grid that has actual stuff. But you may be OK with this! If the reason you wanted width and height to be constant is really to ensure consistency between width and height and the rest of the contents of your Grid object, and you've verified that it doesn't matter whether width and height are replaced before or after other elements of Grid are replaced, then this assignment should be safe because by the end of the assignment, the entire contents of the instance will have been replaced and you'll be back in a consistent state. (If the lack of atomicity of the default assignment was a problem, you could probably get around this by implementing your own assignment operator which used a copy constructor and a swap() operation.)
In summary, what you gain by using read-only getters is the ability to use the objects in a vector or any container with value semantics. However, it then falls to you to ensure that none of Grid's internal operations (or the operations of friends of Grid) violate this consistency, because the compiler won't be locking down the width and height for you. This goes for default construction, copy construction, and assignment as well.
I'm considering making the data member non-const, but private and only accessible by a get function, like this:
class Foo
{
private:
int a;
public:
int getA() const {return a;}
};
Is this 'as good' as const? Does it have any disadvantages?
As of c++20, using const member variables are legal without restrictions that had made it virtually unusable in containers. You still have to define a copy assignment member function because it continues to be automatically deleted when a const object exists in the class. However, changes to "basic.life" now allow changing const sub-objects and c++ provides rather convenient functions for doing this. Here's a description of why the change was made:
The following code shows how to define a copy assignment member function which is useable in any class containing const member objects and uses the new functions std::destroy_at and std::construct_at to fulfil the requirement so the new "basic.life" rules. The code demonstrates assignment of vectors as well as sorting vectors with const elements.
Compiler explorer using MSVC, GCC, CLANG https://godbolt.org/z/McfcaMWqj
#include <memory>
#include <vector>
#include <iostream>
#include <algorithm>
class Foo
{
public:
const int a;
Foo& operator=(const Foo& arg) {
if (this != &arg)
{
std::destroy_at(this);
std::construct_at(this, arg);
}
return *this;
}
};
int main()
{
std::vector<Foo> v;
v.push_back({ 2 });
v.push_back({ 1 });
v.insert(v.begin() + 1, Foo{ 0 });
std::vector<Foo> v2;
v2 = v;
std::sort(v2.begin(), v2.end(), [](auto p1, auto p2) {return p1.a < p2.a; });
for (auto& x : v2)
std::cout << x.a << '\n';
}