Why isn't there a std::construct_at in C++17?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
33
down vote

favorite
6












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);









share|improve this question



















  • 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, but typedef suffices. Is destroy_at solving same problems as make_* wrappers?
    – luk32
    13 hours ago







  • 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







  • 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















up vote
33
down vote

favorite
6












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);









share|improve this question



















  • 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, but typedef suffices. Is destroy_at solving same problems as make_* wrappers?
    – luk32
    13 hours ago







  • 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







  • 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













up vote
33
down vote

favorite
6









up vote
33
down vote

favorite
6






6





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);









share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 15 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 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, but typedef suffices. Is destroy_at solving same problems as make_* wrappers?
    – luk32
    13 hours ago







  • 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







  • 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













  • 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, but typedef suffices. Is destroy_at solving same problems as make_* wrappers?
    – luk32
    13 hours ago







  • 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







  • 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








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













4 Answers
4






active

oldest

votes

















up vote
19
down vote













std::destroy_at provides two objective improvements over a direct destructor call:




  1. 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, putting T there is an element of redundancy. If we change the type to U, we now have to change the destructor call or things break. Using std::destroy_at(ptr) removes the need to change the same thing in two places.



    DRY is good.




  2. 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.






share|improve this answer
















  • 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






  • 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

















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 memory


  • uninitialized_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





share|improve this answer






















  • No emplace-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 is uninitialized_move on the list above.
    – Marek R
    14 hours ago






  • 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







  • 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


















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.






share|improve this answer


















  • 1




    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










  • @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 call std::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


















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.






share|improve this answer


















  • 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










  • 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










  • 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 that construct_at could complete the standard library vocabulary.
    – Oliv
    11 hours ago










Your Answer





StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);













 

draft saved


draft discarded


















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






























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:




  1. 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, putting T there is an element of redundancy. If we change the type to U, we now have to change the destructor call or things break. Using std::destroy_at(ptr) removes the need to change the same thing in two places.



    DRY is good.




  2. 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.






share|improve this answer
















  • 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






  • 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














up vote
19
down vote













std::destroy_at provides two objective improvements over a direct destructor call:




  1. 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, putting T there is an element of redundancy. If we change the type to U, we now have to change the destructor call or things break. Using std::destroy_at(ptr) removes the need to change the same thing in two places.



    DRY is good.




  2. 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.






share|improve this answer
















  • 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






  • 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












up vote
19
down vote










up vote
19
down vote









std::destroy_at provides two objective improvements over a direct destructor call:




  1. 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, putting T there is an element of redundancy. If we change the type to U, we now have to change the destructor call or things break. Using std::destroy_at(ptr) removes the need to change the same thing in two places.



    DRY is good.




  2. 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.






share|improve this answer












std::destroy_at provides two objective improvements over a direct destructor call:




  1. 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, putting T there is an element of redundancy. If we change the type to U, we now have to change the destructor call or things break. Using std::destroy_at(ptr) removes the need to change the same thing in two places.



    DRY is good.




  2. 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.







share|improve this answer












share|improve this answer



share|improve this answer










answered 10 hours ago









Nicol Bolas

276k33452621




276k33452621







  • 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






  • 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












  • 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






  • 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







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












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 memory


  • uninitialized_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





share|improve this answer






















  • No emplace-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 is uninitialized_move on the list above.
    – Marek R
    14 hours ago






  • 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







  • 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















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 memory


  • uninitialized_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





share|improve this answer






















  • No emplace-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 is uninitialized_move on the list above.
    – Marek R
    14 hours ago






  • 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







  • 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













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 memory


  • uninitialized_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





share|improve this answer














There is such a thing, but not named like you might expect:



  • uninitialized_copy
    copies a range of objects to an uninitialized area of memory


  • uninitialized_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






share|improve this answer














share|improve this answer



share|improve this answer








edited 5 hours ago









muru

2,6951647




2,6951647










answered 14 hours ago









Marek R

12.2k22670




12.2k22670











  • No emplace-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 is uninitialized_move on the list above.
    – Marek R
    14 hours ago






  • 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







  • 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

















  • No emplace-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 is uninitialized_move on the list above.
    – Marek R
    14 hours ago






  • 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







  • 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
















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
14 hours ago




there is uninitialized_move on the list above.
– Marek R
14 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











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.






share|improve this answer


















  • 1




    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










  • @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 call std::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















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.






share|improve this answer


















  • 1




    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










  • @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 call std::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













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.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








edited 11 hours ago









Konrad Rudolph

389k1007641015




389k1007641015










answered 14 hours ago









jakub_d

5829




5829







  • 1




    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










  • @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 call std::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




    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










  • @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 call std::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











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.






share|improve this answer


















  • 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










  • 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










  • 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 that construct_at could complete the standard library vocabulary.
    – Oliv
    11 hours ago














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.






share|improve this answer


















  • 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










  • 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










  • 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 that construct_at could complete the standard library vocabulary.
    – Oliv
    11 hours ago












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.






share|improve this answer














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.







share|improve this answer














share|improve this answer



share|improve this answer








edited 10 mins ago









Peter Mortensen

13.2k1983111




13.2k1983111










answered 12 hours ago









Oliv

6,9501749




6,9501749







  • 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










  • 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










  • 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 that construct_at could complete the standard library vocabulary.
    – Oliv
    11 hours ago












  • 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










  • 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










  • 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 that construct_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

















 

draft saved


draft discarded















































 


draft saved


draft discarded














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













































































Comments

Popular posts from this blog

What does second last employer means? [closed]

Installing NextGIS Connect into QGIS 3?

One-line joke