Why isn't there a std::construct_at in C++17?
Clash Royale CLAN TAG#URR8PPP
up vote
33
down vote
favorite
C++17 adds std::destroy_at
, but there isn't any std::construct_at
counterpart. Why is that? Couldn't it be implemented as simply as the following?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args)
return new (addr) T(std::forward<Args>(args)...);
Which would enable to avoid that not-entirely-natural placement new syntax:
void* ptr = ::operator new(sizeof(int));
int* pi = construct_at<int>(ptr, 1); // instead of 'new (ptr) int(1);'
std::cout << *pi;
std::destroy_at(pi);
::operator delete(ptr);
c++ c++17 placement-new
 |Â
show 6 more comments
up vote
33
down vote
favorite
C++17 adds std::destroy_at
, but there isn't any std::construct_at
counterpart. Why is that? Couldn't it be implemented as simply as the following?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args)
return new (addr) T(std::forward<Args>(args)...);
Which would enable to avoid that not-entirely-natural placement new syntax:
void* ptr = ::operator new(sizeof(int));
int* pi = construct_at<int>(ptr, 1); // instead of 'new (ptr) int(1);'
std::cout << *pi;
std::destroy_at(pi);
::operator delete(ptr);
c++ c++17 placement-new
14
in my ignorance i rather wonder whatdestroy_at
is good for ;)
â user463035818
14 hours ago
4
@user463035818 - How would one do a pseudo destructor call for astd::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.
â StoryTeller
14 hours ago
3
@StoryTeller Let me be another one naive, but what is wrong withauto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, buttypedef
suffices. Isdestroy_at
solving same problems asmake_*
wrappers?
â luk32
13 hours ago
3
@luk32 There is no destructor called~string()
. You would have to invokes->~basic_string();
.std::destroy_at(s);
is ok.
â Daniel Langr
13 hours ago
3
@luk32 It worked because you usedusing namespace std;
. Otherwise, you cannot write something ass->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's wherestd::destroy_at
helps.
â Daniel Langr
13 hours ago
 |Â
show 6 more comments
up vote
33
down vote
favorite
up vote
33
down vote
favorite
C++17 adds std::destroy_at
, but there isn't any std::construct_at
counterpart. Why is that? Couldn't it be implemented as simply as the following?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args)
return new (addr) T(std::forward<Args>(args)...);
Which would enable to avoid that not-entirely-natural placement new syntax:
void* ptr = ::operator new(sizeof(int));
int* pi = construct_at<int>(ptr, 1); // instead of 'new (ptr) int(1);'
std::cout << *pi;
std::destroy_at(pi);
::operator delete(ptr);
c++ c++17 placement-new
C++17 adds std::destroy_at
, but there isn't any std::construct_at
counterpart. Why is that? Couldn't it be implemented as simply as the following?
template <typename T, typename... Args>
T* construct_at(void* addr, Args&&... args)
return new (addr) T(std::forward<Args>(args)...);
Which would enable to avoid that not-entirely-natural placement new syntax:
void* ptr = ::operator new(sizeof(int));
int* pi = construct_at<int>(ptr, 1); // instead of 'new (ptr) int(1);'
std::cout << *pi;
std::destroy_at(pi);
::operator delete(ptr);
c++ c++17 placement-new
c++ c++17 placement-new
edited 10 mins ago
Peter Mortensen
13.2k1983111
13.2k1983111
asked 14 hours ago
Daniel Langr
5,7472143
5,7472143
14
in my ignorance i rather wonder whatdestroy_at
is good for ;)
â user463035818
14 hours ago
4
@user463035818 - How would one do a pseudo destructor call for astd::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.
â StoryTeller
14 hours ago
3
@StoryTeller Let me be another one naive, but what is wrong withauto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, buttypedef
suffices. Isdestroy_at
solving same problems asmake_*
wrappers?
â luk32
13 hours ago
3
@luk32 There is no destructor called~string()
. You would have to invokes->~basic_string();
.std::destroy_at(s);
is ok.
â Daniel Langr
13 hours ago
3
@luk32 It worked because you usedusing namespace std;
. Otherwise, you cannot write something ass->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's wherestd::destroy_at
helps.
â Daniel Langr
13 hours ago
 |Â
show 6 more comments
14
in my ignorance i rather wonder whatdestroy_at
is good for ;)
â user463035818
14 hours ago
4
@user463035818 - How would one do a pseudo destructor call for astd::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.
â StoryTeller
14 hours ago
3
@StoryTeller Let me be another one naive, but what is wrong withauto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, buttypedef
suffices. Isdestroy_at
solving same problems asmake_*
wrappers?
â luk32
13 hours ago
3
@luk32 There is no destructor called~string()
. You would have to invokes->~basic_string();
.std::destroy_at(s);
is ok.
â Daniel Langr
13 hours ago
3
@luk32 It worked because you usedusing namespace std;
. Otherwise, you cannot write something ass->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's wherestd::destroy_at
helps.
â Daniel Langr
13 hours ago
14
14
in my ignorance i rather wonder what
destroy_at
is good for ;)â user463035818
14 hours ago
in my ignorance i rather wonder what
destroy_at
is good for ;)â user463035818
14 hours ago
4
4
@user463035818 - How would one do a pseudo destructor call for a
std::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.â StoryTeller
14 hours ago
@user463035818 - How would one do a pseudo destructor call for a
std::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.â StoryTeller
14 hours ago
3
3
@StoryTeller Let me be another one naive, but what is wrong with
auto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, but typedef
suffices. Is destroy_at
solving same problems as make_*
wrappers?â luk32
13 hours ago
@StoryTeller Let me be another one naive, but what is wrong with
auto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, but typedef
suffices. Is destroy_at
solving same problems as make_*
wrappers?â luk32
13 hours ago
3
3
@luk32 There is no destructor called
~string()
. You would have to invoke s->~basic_string();
. std::destroy_at(s);
is ok.â Daniel Langr
13 hours ago
@luk32 There is no destructor called
~string()
. You would have to invoke s->~basic_string();
. std::destroy_at(s);
is ok.â Daniel Langr
13 hours ago
3
3
@luk32 It worked because you used
using namespace std;
. Otherwise, you cannot write something as s->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's where std::destroy_at
helps.â Daniel Langr
13 hours ago
@luk32 It worked because you used
using namespace std;
. Otherwise, you cannot write something as s->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's where std::destroy_at
helps.â Daniel Langr
13 hours ago
 |Â
show 6 more comments
4 Answers
4
active
oldest
votes
up vote
19
down vote
std::destroy_at
provides two objective improvements over a direct destructor call:
It reduces redundancy:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?Sure, we'd all prefer to just wrap it in a
unique_ptr
and be done with it, but if that can't happen for some reason, puttingT
there is an element of redundancy. If we change the type toU
, we now have to change the destructor call or things break. Usingstd::destroy_at(ptr)
removes the need to change the same thing in two places.DRY is good.
It makes this easy:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?If we deduced the type of the pointer, then deleting it becomes kind of hard. You can't do
ptr->~decltype(ptr)()
; since the C++ parser doesn't work that way. Not only that,decltype
deduces the type as a pointer, so you'd need to remove a pointer indirection from the deduced type. Leading you to:auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();And who wants to type that?
By contrast, your hypothetical std::construct_at
provides no objective improvements over placement new
. You have to state the type you're creating in both cases. The parameters to the constructor have to be provided in both cases. The pointer to the memory has to be provided in both cases.
So there is no need being solved by your hypothetical std::construct_at
.
And it is objectively less capable than placement new. You can do this:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T;
These are different. In the first case, the object is default-initialized, which may leave it uninitialized. In the second case, the object is value-initialized.
Your hypothetical std::construct_at
cannot allow you to pick which one you want. It can have code that performs default initialization if you provide no parameters, but it would then be unable to provide a version for value initialization. And it could value initialize with no parameters, but then you couldn't default initialize the object.
3
It's a pity that the Standards committee didn't just add support for the syntaxptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.
â Sneftel
9 hours ago
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of ifauto
refers to the type of the pointer or the type it was constructed with (or the type of iterator ifptr
is actually an iterator!).
â Jon Harper
8 hours ago
add a comment |Â
up vote
12
down vote
There is such a thing, but not named like you might expect:
uninitialized_copy
copies a range of objects to an uninitialized area of memoryuninitialized_copy_n
(C++11)
copies a number of objects to an uninitialized area of memory
(function template)uninitialized_fill
copies an object to an uninitialized area of memory, defined by a range
(function template)
uninitialized_fill_n
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_move
(C++17)
moves a range of objects to an uninitialized area of memory
(function template)
uninitialized_move_n
(C++17)
moves a number of objects to an uninitialized area of memory
(function template)
uninitialized_default_construct
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_default_construct_n
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_value_construct
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_value_construct_n
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
Noemplace
-style parameter-forwarding function though.
â Quentin
14 hours ago
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there isuninitialized_move
on the list above.
â Marek R
13 hours ago
3
@MarekR How would you usestd::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument ofstd::uninitialized_move
, which represents a destination iterator?
â Daniel Langr
13 hours ago
5
This makes no sense, -1. Those are all range algorithms. In the same way that we havestd::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.
â Barry
9 hours ago
 |Â
show 3 more comments
up vote
7
down vote
There is std::allocator_traits::construct
. There used to be one more in std::allocator
, but that got removed, rationale in standards committee paper D0174R0.
1
There is alsostd::allocator_traits::destroy
and still, there isstd::destroy_at
as well.
â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggestedstd::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.
â Konrad Rudolph
11 hours ago
@KonradRudolph:allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it.destroy_at
is for destroying an object by calling its destructor.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: Or you could just callstd::destroy_at
.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
 |Â
show 6 more comments
up vote
0
down vote
construct
does not seem to provide any syntactic sugar. Moreover it is less efficient than a placement new. Binding to reference arguments cause temporary materialization and extra move/copy construction:
struct heavy
unsigned char[4096];
heavy(const heavy&);
;
heavy make_heavy(); // Return a pr-value
auto loc = ::operator new(sizeof(heavy));
// Equivalently: unsigned char loc[sizeof(heavy)];
auto p = construct<heavy>(loc,make_heavy()); // The pr-value returned by
// make_heavy is bound to the second argument,
// and then this arugment is copied in the body of construct.
auto p2 = new(loc) auto(make_heavy()); // Heavy is directly constructed at loc
//... and this is simpler to write!
Unfortunately there isn't any way to avoid these extra copy/move construction when calling a function. Forwarding is almost perfect.
On the other hand, construct_at
in the library could complete the standard library vocabulary.
1
That could be easily incorporated intoconstruct_at
as well, by returning aT*
pointer from placement new. That's not a reason why such a function could not exist.
â Daniel Langr
12 hours ago
By the way, how would you implement astd::vector
? When youpush_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) inoperator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same asptr
in the code above.
â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
@DanielLangr I think we are close to the opion based question/answer. Because I think thatconstruct_at
could complete the standard library vocabulary.
â Oliv
11 hours ago
 |Â
show 5 more comments
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
19
down vote
std::destroy_at
provides two objective improvements over a direct destructor call:
It reduces redundancy:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?Sure, we'd all prefer to just wrap it in a
unique_ptr
and be done with it, but if that can't happen for some reason, puttingT
there is an element of redundancy. If we change the type toU
, we now have to change the destructor call or things break. Usingstd::destroy_at(ptr)
removes the need to change the same thing in two places.DRY is good.
It makes this easy:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?If we deduced the type of the pointer, then deleting it becomes kind of hard. You can't do
ptr->~decltype(ptr)()
; since the C++ parser doesn't work that way. Not only that,decltype
deduces the type as a pointer, so you'd need to remove a pointer indirection from the deduced type. Leading you to:auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();And who wants to type that?
By contrast, your hypothetical std::construct_at
provides no objective improvements over placement new
. You have to state the type you're creating in both cases. The parameters to the constructor have to be provided in both cases. The pointer to the memory has to be provided in both cases.
So there is no need being solved by your hypothetical std::construct_at
.
And it is objectively less capable than placement new. You can do this:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T;
These are different. In the first case, the object is default-initialized, which may leave it uninitialized. In the second case, the object is value-initialized.
Your hypothetical std::construct_at
cannot allow you to pick which one you want. It can have code that performs default initialization if you provide no parameters, but it would then be unable to provide a version for value initialization. And it could value initialize with no parameters, but then you couldn't default initialize the object.
3
It's a pity that the Standards committee didn't just add support for the syntaxptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.
â Sneftel
9 hours ago
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of ifauto
refers to the type of the pointer or the type it was constructed with (or the type of iterator ifptr
is actually an iterator!).
â Jon Harper
8 hours ago
add a comment |Â
up vote
19
down vote
std::destroy_at
provides two objective improvements over a direct destructor call:
It reduces redundancy:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?Sure, we'd all prefer to just wrap it in a
unique_ptr
and be done with it, but if that can't happen for some reason, puttingT
there is an element of redundancy. If we change the type toU
, we now have to change the destructor call or things break. Usingstd::destroy_at(ptr)
removes the need to change the same thing in two places.DRY is good.
It makes this easy:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?If we deduced the type of the pointer, then deleting it becomes kind of hard. You can't do
ptr->~decltype(ptr)()
; since the C++ parser doesn't work that way. Not only that,decltype
deduces the type as a pointer, so you'd need to remove a pointer indirection from the deduced type. Leading you to:auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();And who wants to type that?
By contrast, your hypothetical std::construct_at
provides no objective improvements over placement new
. You have to state the type you're creating in both cases. The parameters to the constructor have to be provided in both cases. The pointer to the memory has to be provided in both cases.
So there is no need being solved by your hypothetical std::construct_at
.
And it is objectively less capable than placement new. You can do this:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T;
These are different. In the first case, the object is default-initialized, which may leave it uninitialized. In the second case, the object is value-initialized.
Your hypothetical std::construct_at
cannot allow you to pick which one you want. It can have code that performs default initialization if you provide no parameters, but it would then be unable to provide a version for value initialization. And it could value initialize with no parameters, but then you couldn't default initialize the object.
3
It's a pity that the Standards committee didn't just add support for the syntaxptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.
â Sneftel
9 hours ago
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of ifauto
refers to the type of the pointer or the type it was constructed with (or the type of iterator ifptr
is actually an iterator!).
â Jon Harper
8 hours ago
add a comment |Â
up vote
19
down vote
up vote
19
down vote
std::destroy_at
provides two objective improvements over a direct destructor call:
It reduces redundancy:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?Sure, we'd all prefer to just wrap it in a
unique_ptr
and be done with it, but if that can't happen for some reason, puttingT
there is an element of redundancy. If we change the type toU
, we now have to change the destructor call or things break. Usingstd::destroy_at(ptr)
removes the need to change the same thing in two places.DRY is good.
It makes this easy:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?If we deduced the type of the pointer, then deleting it becomes kind of hard. You can't do
ptr->~decltype(ptr)()
; since the C++ parser doesn't work that way. Not only that,decltype
deduces the type as a pointer, so you'd need to remove a pointer indirection from the deduced type. Leading you to:auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();And who wants to type that?
By contrast, your hypothetical std::construct_at
provides no objective improvements over placement new
. You have to state the type you're creating in both cases. The parameters to the constructor have to be provided in both cases. The pointer to the memory has to be provided in both cases.
So there is no need being solved by your hypothetical std::construct_at
.
And it is objectively less capable than placement new. You can do this:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T;
These are different. In the first case, the object is default-initialized, which may leave it uninitialized. In the second case, the object is value-initialized.
Your hypothetical std::construct_at
cannot allow you to pick which one you want. It can have code that performs default initialization if you provide no parameters, but it would then be unable to provide a version for value initialization. And it could value initialize with no parameters, but then you couldn't default initialize the object.
std::destroy_at
provides two objective improvements over a direct destructor call:
It reduces redundancy:
T *ptr = new T;
//Insert 1000 lines of code here.
ptr->~T(); //What type was that again?Sure, we'd all prefer to just wrap it in a
unique_ptr
and be done with it, but if that can't happen for some reason, puttingT
there is an element of redundancy. If we change the type toU
, we now have to change the destructor call or things break. Usingstd::destroy_at(ptr)
removes the need to change the same thing in two places.DRY is good.
It makes this easy:
auto ptr = allocates_an_object(...);
//Insert code here
ptr->~???; //What type is that again?If we deduced the type of the pointer, then deleting it becomes kind of hard. You can't do
ptr->~decltype(ptr)()
; since the C++ parser doesn't work that way. Not only that,decltype
deduces the type as a pointer, so you'd need to remove a pointer indirection from the deduced type. Leading you to:auto ptr = allocates_an_object(...);
//Insert code here
using delete_type = std::remove_pointer_t<decltype(ptr)>;
ptr->~delete_type();And who wants to type that?
By contrast, your hypothetical std::construct_at
provides no objective improvements over placement new
. You have to state the type you're creating in both cases. The parameters to the constructor have to be provided in both cases. The pointer to the memory has to be provided in both cases.
So there is no need being solved by your hypothetical std::construct_at
.
And it is objectively less capable than placement new. You can do this:
auto ptr1 = new(mem1) T;
auto ptr2 = new(mem2) T;
These are different. In the first case, the object is default-initialized, which may leave it uninitialized. In the second case, the object is value-initialized.
Your hypothetical std::construct_at
cannot allow you to pick which one you want. It can have code that performs default initialization if you provide no parameters, but it would then be unable to provide a version for value initialization. And it could value initialize with no parameters, but then you couldn't default initialize the object.
answered 10 hours ago
Nicol Bolas
276k33452621
276k33452621
3
It's a pity that the Standards committee didn't just add support for the syntaxptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.
â Sneftel
9 hours ago
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of ifauto
refers to the type of the pointer or the type it was constructed with (or the type of iterator ifptr
is actually an iterator!).
â Jon Harper
8 hours ago
add a comment |Â
3
It's a pity that the Standards committee didn't just add support for the syntaxptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.
â Sneftel
9 hours ago
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of ifauto
refers to the type of the pointer or the type it was constructed with (or the type of iterator ifptr
is actually an iterator!).
â Jon Harper
8 hours ago
3
3
It's a pity that the Standards committee didn't just add support for the syntax
ptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.â Sneftel
9 hours ago
It's a pity that the Standards committee didn't just add support for the syntax
ptr->~auto();
... but perhaps there's a most-vexing-parse sort of issue there.â Sneftel
9 hours ago
2
2
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of if
auto
refers to the type of the pointer or the type it was constructed with (or the type of iterator if ptr
is actually an iterator!).â Jon Harper
8 hours ago
@Sneftel I doubt it's an MVP issue. I imagine it's a combination of 1) the committee's conservative approach to new syntax and 2) the question of if
auto
refers to the type of the pointer or the type it was constructed with (or the type of iterator if ptr
is actually an iterator!).â Jon Harper
8 hours ago
add a comment |Â
up vote
12
down vote
There is such a thing, but not named like you might expect:
uninitialized_copy
copies a range of objects to an uninitialized area of memoryuninitialized_copy_n
(C++11)
copies a number of objects to an uninitialized area of memory
(function template)uninitialized_fill
copies an object to an uninitialized area of memory, defined by a range
(function template)
uninitialized_fill_n
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_move
(C++17)
moves a range of objects to an uninitialized area of memory
(function template)
uninitialized_move_n
(C++17)
moves a number of objects to an uninitialized area of memory
(function template)
uninitialized_default_construct
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_default_construct_n
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_value_construct
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_value_construct_n
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
Noemplace
-style parameter-forwarding function though.
â Quentin
14 hours ago
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there isuninitialized_move
on the list above.
â Marek R
13 hours ago
3
@MarekR How would you usestd::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument ofstd::uninitialized_move
, which represents a destination iterator?
â Daniel Langr
13 hours ago
5
This makes no sense, -1. Those are all range algorithms. In the same way that we havestd::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.
â Barry
9 hours ago
 |Â
show 3 more comments
up vote
12
down vote
There is such a thing, but not named like you might expect:
uninitialized_copy
copies a range of objects to an uninitialized area of memoryuninitialized_copy_n
(C++11)
copies a number of objects to an uninitialized area of memory
(function template)uninitialized_fill
copies an object to an uninitialized area of memory, defined by a range
(function template)
uninitialized_fill_n
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_move
(C++17)
moves a range of objects to an uninitialized area of memory
(function template)
uninitialized_move_n
(C++17)
moves a number of objects to an uninitialized area of memory
(function template)
uninitialized_default_construct
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_default_construct_n
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_value_construct
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_value_construct_n
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
Noemplace
-style parameter-forwarding function though.
â Quentin
14 hours ago
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there isuninitialized_move
on the list above.
â Marek R
13 hours ago
3
@MarekR How would you usestd::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument ofstd::uninitialized_move
, which represents a destination iterator?
â Daniel Langr
13 hours ago
5
This makes no sense, -1. Those are all range algorithms. In the same way that we havestd::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.
â Barry
9 hours ago
 |Â
show 3 more comments
up vote
12
down vote
up vote
12
down vote
There is such a thing, but not named like you might expect:
uninitialized_copy
copies a range of objects to an uninitialized area of memoryuninitialized_copy_n
(C++11)
copies a number of objects to an uninitialized area of memory
(function template)uninitialized_fill
copies an object to an uninitialized area of memory, defined by a range
(function template)
uninitialized_fill_n
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_move
(C++17)
moves a range of objects to an uninitialized area of memory
(function template)
uninitialized_move_n
(C++17)
moves a number of objects to an uninitialized area of memory
(function template)
uninitialized_default_construct
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_default_construct_n
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_value_construct
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_value_construct_n
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
There is such a thing, but not named like you might expect:
uninitialized_copy
copies a range of objects to an uninitialized area of memoryuninitialized_copy_n
(C++11)
copies a number of objects to an uninitialized area of memory
(function template)uninitialized_fill
copies an object to an uninitialized area of memory, defined by a range
(function template)
uninitialized_fill_n
copies an object to an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_move
(C++17)
moves a range of objects to an uninitialized area of memory
(function template)
uninitialized_move_n
(C++17)
moves a number of objects to an uninitialized area of memory
(function template)
uninitialized_default_construct
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_default_construct_n
(C++17)
constructs objects by default-initialization in an uninitialized area of memory, defined by a start and a count
(function template)
uninitialized_value_construct
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a range
(function template)
uninitialized_value_construct_n
(C++17)
constructs objects by value-initialization in an uninitialized area of memory, defined by a start and a count
edited 5 hours ago
muru
2,6951647
2,6951647
answered 14 hours ago
Marek R
12.2k22670
12.2k22670
Noemplace
-style parameter-forwarding function though.
â Quentin
14 hours ago
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there isuninitialized_move
on the list above.
â Marek R
13 hours ago
3
@MarekR How would you usestd::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument ofstd::uninitialized_move
, which represents a destination iterator?
â Daniel Langr
13 hours ago
5
This makes no sense, -1. Those are all range algorithms. In the same way that we havestd::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.
â Barry
9 hours ago
 |Â
show 3 more comments
Noemplace
-style parameter-forwarding function though.
â Quentin
14 hours ago
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there isuninitialized_move
on the list above.
â Marek R
13 hours ago
3
@MarekR How would you usestd::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument ofstd::uninitialized_move
, which represents a destination iterator?
â Daniel Langr
13 hours ago
5
This makes no sense, -1. Those are all range algorithms. In the same way that we havestd::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.
â Barry
9 hours ago
No
emplace
-style parameter-forwarding function though.â Quentin
14 hours ago
No
emplace
-style parameter-forwarding function though.â Quentin
14 hours ago
1
1
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
Is any of these functions able to forward arbitrary arguments to constructor?
â Daniel Langr
14 hours ago
there is
uninitialized_move
on the list above.â Marek R
13 hours ago
there is
uninitialized_move
on the list above.â Marek R
13 hours ago
3
3
@MarekR How would you use
std::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument of std::uninitialized_move
, which represents a destination iterator?â Daniel Langr
13 hours ago
@MarekR How would you use
std::uninitialized_move
to construct a single object while forwarding arguments? What would you use as a 3rd argument of std::uninitialized_move
, which represents a destination iterator?â Daniel Langr
13 hours ago
5
5
This makes no sense, -1. Those are all range algorithms. In the same way that we have
std::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.â Barry
9 hours ago
This makes no sense, -1. Those are all range algorithms. In the same way that we have
std::destroy()
which is the range destruction algorithm. We're talking about a single construction - there are not N variations of construction. Or rather, there are variations (list-init, paren-init, default-init) but an algorithm wouldn't capture that. See Nicol's answer.â Barry
9 hours ago
 |Â
show 3 more comments
up vote
7
down vote
There is std::allocator_traits::construct
. There used to be one more in std::allocator
, but that got removed, rationale in standards committee paper D0174R0.
1
There is alsostd::allocator_traits::destroy
and still, there isstd::destroy_at
as well.
â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggestedstd::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.
â Konrad Rudolph
11 hours ago
@KonradRudolph:allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it.destroy_at
is for destroying an object by calling its destructor.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: Or you could just callstd::destroy_at
.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
 |Â
show 6 more comments
up vote
7
down vote
There is std::allocator_traits::construct
. There used to be one more in std::allocator
, but that got removed, rationale in standards committee paper D0174R0.
1
There is alsostd::allocator_traits::destroy
and still, there isstd::destroy_at
as well.
â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggestedstd::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.
â Konrad Rudolph
11 hours ago
@KonradRudolph:allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it.destroy_at
is for destroying an object by calling its destructor.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: Or you could just callstd::destroy_at
.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
 |Â
show 6 more comments
up vote
7
down vote
up vote
7
down vote
There is std::allocator_traits::construct
. There used to be one more in std::allocator
, but that got removed, rationale in standards committee paper D0174R0.
There is std::allocator_traits::construct
. There used to be one more in std::allocator
, but that got removed, rationale in standards committee paper D0174R0.
edited 11 hours ago
Konrad Rudolph
389k1007641015
389k1007641015
answered 14 hours ago
jakub_d
5829
5829
1
There is alsostd::allocator_traits::destroy
and still, there isstd::destroy_at
as well.
â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggestedstd::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.
â Konrad Rudolph
11 hours ago
@KonradRudolph:allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it.destroy_at
is for destroying an object by calling its destructor.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: Or you could just callstd::destroy_at
.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
 |Â
show 6 more comments
1
There is alsostd::allocator_traits::destroy
and still, there isstd::destroy_at
as well.
â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggestedstd::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.
â Konrad Rudolph
11 hours ago
@KonradRudolph:allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it.destroy_at
is for destroying an object by calling its destructor.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: Or you could just callstd::destroy_at
.
â Nicol Bolas
10 hours ago
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
1
1
There is also
std::allocator_traits::destroy
and still, there is std::destroy_at
as well.â Daniel Langr
14 hours ago
There is also
std::allocator_traits::destroy
and still, there is std::destroy_at
as well.â Daniel Langr
14 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggested
std::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.â Konrad Rudolph
11 hours ago
@DanielLangr IMHO itâÂÂs a better question who this redundancy exists. Whoever suggested
std::destroy_at
for inclusion probably had a specific use-case in mind but IâÂÂm not sure why the committee went along.â Konrad Rudolph
11 hours ago
@KonradRudolph:
allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it. destroy_at
is for destroying an object by calling its destructor.â Nicol Bolas
10 hours ago
@KonradRudolph:
allocator_traits::destroy
is for destroying an object allocated through an allocator. That means you have to pass it an allocator object that can destroy it. destroy_at
is for destroying an object by calling its destructor.â Nicol Bolas
10 hours ago
2
2
@KonradRudolph: Or you could just call
std::destroy_at
.â Nicol Bolas
10 hours ago
@KonradRudolph: Or you could just call
std::destroy_at
.â Nicol Bolas
10 hours ago
2
2
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
@KonradRudolph: My point is that there is no redundancy. They're doing two different things, via two different mechanisms, for two different reasons... that happen to work out to be the same thing in this particular case.
â Nicol Bolas
10 hours ago
 |Â
show 6 more comments
up vote
0
down vote
construct
does not seem to provide any syntactic sugar. Moreover it is less efficient than a placement new. Binding to reference arguments cause temporary materialization and extra move/copy construction:
struct heavy
unsigned char[4096];
heavy(const heavy&);
;
heavy make_heavy(); // Return a pr-value
auto loc = ::operator new(sizeof(heavy));
// Equivalently: unsigned char loc[sizeof(heavy)];
auto p = construct<heavy>(loc,make_heavy()); // The pr-value returned by
// make_heavy is bound to the second argument,
// and then this arugment is copied in the body of construct.
auto p2 = new(loc) auto(make_heavy()); // Heavy is directly constructed at loc
//... and this is simpler to write!
Unfortunately there isn't any way to avoid these extra copy/move construction when calling a function. Forwarding is almost perfect.
On the other hand, construct_at
in the library could complete the standard library vocabulary.
1
That could be easily incorporated intoconstruct_at
as well, by returning aT*
pointer from placement new. That's not a reason why such a function could not exist.
â Daniel Langr
12 hours ago
By the way, how would you implement astd::vector
? When youpush_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) inoperator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same asptr
in the code above.
â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
@DanielLangr I think we are close to the opion based question/answer. Because I think thatconstruct_at
could complete the standard library vocabulary.
â Oliv
11 hours ago
 |Â
show 5 more comments
up vote
0
down vote
construct
does not seem to provide any syntactic sugar. Moreover it is less efficient than a placement new. Binding to reference arguments cause temporary materialization and extra move/copy construction:
struct heavy
unsigned char[4096];
heavy(const heavy&);
;
heavy make_heavy(); // Return a pr-value
auto loc = ::operator new(sizeof(heavy));
// Equivalently: unsigned char loc[sizeof(heavy)];
auto p = construct<heavy>(loc,make_heavy()); // The pr-value returned by
// make_heavy is bound to the second argument,
// and then this arugment is copied in the body of construct.
auto p2 = new(loc) auto(make_heavy()); // Heavy is directly constructed at loc
//... and this is simpler to write!
Unfortunately there isn't any way to avoid these extra copy/move construction when calling a function. Forwarding is almost perfect.
On the other hand, construct_at
in the library could complete the standard library vocabulary.
1
That could be easily incorporated intoconstruct_at
as well, by returning aT*
pointer from placement new. That's not a reason why such a function could not exist.
â Daniel Langr
12 hours ago
By the way, how would you implement astd::vector
? When youpush_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) inoperator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same asptr
in the code above.
â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
@DanielLangr I think we are close to the opion based question/answer. Because I think thatconstruct_at
could complete the standard library vocabulary.
â Oliv
11 hours ago
 |Â
show 5 more comments
up vote
0
down vote
up vote
0
down vote
construct
does not seem to provide any syntactic sugar. Moreover it is less efficient than a placement new. Binding to reference arguments cause temporary materialization and extra move/copy construction:
struct heavy
unsigned char[4096];
heavy(const heavy&);
;
heavy make_heavy(); // Return a pr-value
auto loc = ::operator new(sizeof(heavy));
// Equivalently: unsigned char loc[sizeof(heavy)];
auto p = construct<heavy>(loc,make_heavy()); // The pr-value returned by
// make_heavy is bound to the second argument,
// and then this arugment is copied in the body of construct.
auto p2 = new(loc) auto(make_heavy()); // Heavy is directly constructed at loc
//... and this is simpler to write!
Unfortunately there isn't any way to avoid these extra copy/move construction when calling a function. Forwarding is almost perfect.
On the other hand, construct_at
in the library could complete the standard library vocabulary.
construct
does not seem to provide any syntactic sugar. Moreover it is less efficient than a placement new. Binding to reference arguments cause temporary materialization and extra move/copy construction:
struct heavy
unsigned char[4096];
heavy(const heavy&);
;
heavy make_heavy(); // Return a pr-value
auto loc = ::operator new(sizeof(heavy));
// Equivalently: unsigned char loc[sizeof(heavy)];
auto p = construct<heavy>(loc,make_heavy()); // The pr-value returned by
// make_heavy is bound to the second argument,
// and then this arugment is copied in the body of construct.
auto p2 = new(loc) auto(make_heavy()); // Heavy is directly constructed at loc
//... and this is simpler to write!
Unfortunately there isn't any way to avoid these extra copy/move construction when calling a function. Forwarding is almost perfect.
On the other hand, construct_at
in the library could complete the standard library vocabulary.
edited 4 mins ago
Peter Mortensen
13.2k1983111
13.2k1983111
answered 12 hours ago
Oliv
6,9501749
6,9501749
1
That could be easily incorporated intoconstruct_at
as well, by returning aT*
pointer from placement new. That's not a reason why such a function could not exist.
â Daniel Langr
12 hours ago
By the way, how would you implement astd::vector
? When youpush_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) inoperator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same asptr
in the code above.
â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
@DanielLangr I think we are close to the opion based question/answer. Because I think thatconstruct_at
could complete the standard library vocabulary.
â Oliv
11 hours ago
 |Â
show 5 more comments
1
That could be easily incorporated intoconstruct_at
as well, by returning aT*
pointer from placement new. That's not a reason why such a function could not exist.
â Daniel Langr
12 hours ago
By the way, how would you implement astd::vector
? When youpush_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) inoperator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same asptr
in the code above.
â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
@DanielLangr I think we are close to the opion based question/answer. Because I think thatconstruct_at
could complete the standard library vocabulary.
â Oliv
11 hours ago
1
1
That could be easily incorporated into
construct_at
as well, by returning a T*
pointer from placement new. That's not a reason why such a function could not exist.â Daniel Langr
12 hours ago
That could be easily incorporated into
construct_at
as well, by returning a T*
pointer from placement new. That's not a reason why such a function could not exist.â Daniel Langr
12 hours ago
By the way, how would you implement a
std::vector
? When you push_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) in operator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same as ptr
in the code above.â Daniel Langr
12 hours ago
By the way, how would you implement a
std::vector
? When you push_back
/emplace_back
, you need to use placement new to create an object in vector's buffer. And then, you don't return this particular pointer (returned by placement new) in operator()
. You simply return a pointer from some member variable incremetned by some index. Which is the same as ptr
in the code above.â Daniel Langr
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
@DanielLangr It is a well known problem, std::vector is not implementable (or easily, I think I have a solution) if one only try to use core language.
â Oliv
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
All right, didn't know this.
â Daniel Langr
12 hours ago
1
1
@DanielLangr I think we are close to the opion based question/answer. Because I think that
construct_at
could complete the standard library vocabulary.â Oliv
11 hours ago
@DanielLangr I think we are close to the opion based question/answer. Because I think that
construct_at
could complete the standard library vocabulary.â Oliv
11 hours ago
 |Â
show 5 more comments
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f52966560%2fwhy-isnt-there-a-stdconstruct-at-in-c17%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
14
in my ignorance i rather wonder what
destroy_at
is good for ;)â user463035818
14 hours ago
4
@user463035818 - How would one do a pseudo destructor call for a
std::string
object? Don't get me wrong, I'm not saying it's impossible, I just want you to imagine the required expression vividly.â StoryTeller
14 hours ago
3
@StoryTeller Let me be another one naive, but what is wrong with
auto s = new string"test"; s->~string();
? Am I missing premise of the question? I guess calling pseudo destructors on compound template types would be syntax nightmare, buttypedef
suffices. Isdestroy_at
solving same problems asmake_*
wrappers?â luk32
13 hours ago
3
@luk32 There is no destructor called
~string()
. You would have to invokes->~basic_string();
.std::destroy_at(s);
is ok.â Daniel Langr
13 hours ago
3
@luk32 It worked because you used
using namespace std;
. Otherwise, you cannot write something ass->~std::string();
, or, at least, compilers don't compile it (see, e.g., here: stackoverflow.com/q/24593942/580083 for related discussion). That's wherestd::destroy_at
helps.â Daniel Langr
13 hours ago