Why does emplacement allow you to discard const

Jun 24, 2021 at 3:11pm
Why does the following compile?

class Fred
{
public:
Fred(int value):
i(value)
{
}

Fred(Fred const&) = delete;
Fred const& operator = (Fred const&) = delete;

private:
int i;
};

Fred const MakeFred()
{
return Fred(1);
}

TEST(Temparies, Fred)
{
Fred A = MakeFred(); // !! Discarding const !!
//Fred &B = MakeFred(); // Compile error - drops const
}
Jun 24, 2021 at 3:24pm
Fred A = MakeFred(); // !! Discarding const !!
You're making a copy here, so it's not 'discarding' the const, rather it's a completely separate object.
<edit: I'm a fool, I didn't see you deleted the copy ctor. TomCPP is correct; it requires copy elision. But note that the 'const' on that by-value return type is ignored by the compiler, so this isn't about the constness of it>

//Fred &B = MakeFred(); // Compile error - drops const
MakeFred() returns a temporary object. You can't have a non-const reference to a temporary.
Last edited on Jun 24, 2021 at 9:59pm
Jun 24, 2021 at 3:52pm
This code only compiles in C++17 or higher standard.
Jul 2, 2021 at 7:56am
I kind of understand why the copy elision allows this

Fred A = MakeFred(); // !! Discarding const !!

However the clear intention is that the object returned by MakeFred() is const (not modifiable). But in this case the object returned (A) is modifiable which breaks the intent and may cause bugs.
Jul 2, 2021 at 8:29am
> However the clear intention is that the object returned by MakeFred() is const (not modifiable).

There is no (temporary) object returned by MakeFred() that is involved in the initialisation of FredA;
the value returned is just a prvalue which is used as the initialiser.

C++17 core language specification of prvalues and temporaries is fundamentally different from that of the earlier C++ revisions: there is no longer a temporary to copy/move from. Another way to describe C++17 mechanics is "unmaterialized value passing": prvalues are returned and used without ever materializing a temporary.
https://en.cppreference.com/w/cpp/language/copy_elision
Jul 2, 2021 at 11:00am
This blog talks about your const return type, and pretty much says it all.
https://www.sandordargo.com/blog/2020/11/18/when-use-const-3-return-types

I've copied the first part of that blog here, it does go on further, and with examples.
Returning const objects by value

If you’re really enthusiastic about turning everything into const and that’s your first time to do so, you might start converting signatures like std::string getName() const into const std::string getName() const. The only problem is that most probably it won’t make so much sense.

Why is that?

Putting const somewhere shows the reader (and the compiler of course) that something should not be modified. When we return something by value it means that a copy will be made for the caller. Okay, you might have heard about copy elision and its special form, return value optimization (RVO), but essentially we are still on the same page. The caller gets his own copy.
Last edited on Jul 2, 2021 at 11:01am
Topic archived. No new replies allowed.