Why does emplacement allow you to discard const

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
}
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
This code only compiles in C++17 or higher standard.
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.
> 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
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
Topic archived. No new replies allowed.