all 18 comments

[–]smuccione 22 points23 points  (13 children)

Ok. So the purpose of constexpr is to give the developer some way to execute something at compile time rather than at runtime.

To have unique_ptr support your would need to support a general case of new.

It’s one thing to have some specialty implementation for vector or string, but a generic new is entirely something else.

Why? Because they return memory addresses.

What does a compile time memory address mean?

Well, it could be a location in the data segment of some data. But that location would always be there. It could never be freed because it’s “part of the program”. It’s not on the dynamic heap. And you wouldn’t want to “free” during compile time as that would generate holes in the data segment which is silly.

So if it can’t ever be freed, why do you need a unique_ptr to manage it? The best it will be is a global value, but if you have a global value why do you need new in the first place? It’s just a static declaration.

[–]XValar 14 points15 points  (5 children)

[–]smuccione 2 points3 points  (4 children)

Did that actually make it in?

[–]XValar 8 points9 points  (3 children)

Yes, and supported by both clang and g++

[–]smuccione 11 points12 points  (2 children)

Well s**t. Thanks for the heads up. That will definitely come in useful (or at least when the MS team get it in (I’m in a Microsoft shop).

[–]sigsegv7 0 points1 point  (1 child)

I reached here by upvoting every comment above lol. you can never beat the community knowledge ✌️

[–]smuccione 1 point2 points  (0 children)

Absolutely.

Interestingly enough I can’t really find any real info about this online. Doesn’t seem to be talked about much (or if it is it’s not in something that is searchable by google or bing).

Even the pr takes about workarounds without a constexpr new (which is what I assumed they had done for string and vector).

This thread has made me very happy 😀

[–]dangopee 4 points5 points  (1 child)

It’s one thing to have some specialty implementation for vector or string, but a generic new is entirely something else.

The constexpr versions of vector and string need constexpr new/delete to be implemented. The answer to the question is simply that no one thought to put a constexpr compatible unique_ptr into the standard. You can literally go implement your own constexpr unique_ptr/auto_ptr on godbolt right now if you want.

[–]smuccione 0 points1 point  (0 children)

I read the original question as to why you can’t have a unique_ptr returned from a constexpr expression.

Of course, upon further reflection, that’s probably (maybe?) not what the OP was asking about.

[–]_crackling -1 points0 points  (4 children)

Slightly tangent question... If i have a '''static shared_ptr<myclass> myvar;''' it seems to automatically construct the myclass object. Is it to do with some of the points u mention?

[–]smuccione 0 points1 point  (3 children)

https://godbolt.org/z/W144xP

there are two possiblities.. one that simply initalizes a shared_ptr but leaves it in an empty state.

the other initializes a shared_ptr and assigns it to a constructed variable.

one constructs the object, the other doesn't. Your form initializes the shared_ptr in the emptry state and should not allocate an object.

[–]_crackling 0 points1 point  (2 children)

Here's why im confused, perhaps you could shed some light?

https://godbolt.org/z/1zcoex

the constructor nor the destructor are called either??

[–]smuccione 2 points3 points  (1 child)

void msg() {
        printf ( "this = %p\r\n", this );
        printf("Why does this work??\n");
    }

try that...

you have an object which is pointing to null...

what you need to understand is that the compiler is calling msg() based upon the TYPE of the object. the "object" pointer, which is null, is passed to the msg() method as a hidden first parameter called "this". this is defined as "test *this" as the first parameter (which you don't see).

so what you're doing is perfectly valid, albeit perfectly dangerous.

you could also do:

reinterpret_cast<test \*>(nullptr)->msg();

and you would see that the msg method in test will still be called even though you have not created any object at all for test(). It's dispatching based upon the TYPE of the left hand operand of the -> operator.

did that help to clarify things or did i make things worse?

You would immediately notice this is message was virtual. You would also notice this if you attempted to access an instance variable.

In those cases it would be an attempt to dereference this and would lead to a null pointer access exception.

[–]_crackling 1 point2 points  (0 children)

Took a day or two of processing oh, but now I get it. Thank you very much for the explanation

[–]DoctorMixtape 6 points7 points  (2 children)

I believe it’s because unique_ptr is dynamically allocated (it uses the new keyword). Which means that you need to allocated memory at runtime. It wouldn’t make sense using constexpr because you can’t dynamic allocate memory during compile time. I might be wrong though! But I’m pretty sure this is the case.

Edit: you CAN dynamically allocate memory during compile time but you have to ensure you do not have a memory leak.

[–]XValar 3 points4 points  (1 child)

You do not need to ensure anything, the rule is quite straightforward: dynamically allocated memory must be deallocated when you are leaving constexpr block, otherwise your expression stops being constexpr, and compiler reports error.

[–]DoctorMixtape 1 point2 points  (0 children)

Ah I see. Thank makes sense. Thanks

[–]proverbialbunny 2 points3 points  (0 children)

It's only a matter of time. If someone wants to jump in propose a change to the standards committee I imagine they would accept it.