Why is try_emplace not implemented for std::multimap?












9














C++17 introduces the try_emplace method for std::map, so now I can write code like below:



struct Test
{
Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);


But there is no try_emplace for std::multimap<int, Test>, so piecewise_construct is still needed.



Is there a technical reason for this?










share|improve this question




















  • 2




    std::multimap does not need try_emplace as it always inserts, so emplace is enough.
    – Slava
    Dec 14 '18 at 1:26










  • I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
    – Lei Yu
    Dec 14 '18 at 5:46
















9














C++17 introduces the try_emplace method for std::map, so now I can write code like below:



struct Test
{
Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);


But there is no try_emplace for std::multimap<int, Test>, so piecewise_construct is still needed.



Is there a technical reason for this?










share|improve this question




















  • 2




    std::multimap does not need try_emplace as it always inserts, so emplace is enough.
    – Slava
    Dec 14 '18 at 1:26










  • I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
    – Lei Yu
    Dec 14 '18 at 5:46














9












9








9







C++17 introduces the try_emplace method for std::map, so now I can write code like below:



struct Test
{
Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);


But there is no try_emplace for std::multimap<int, Test>, so piecewise_construct is still needed.



Is there a technical reason for this?










share|improve this question















C++17 introduces the try_emplace method for std::map, so now I can write code like below:



struct Test
{
Test(int i, int j){}
};
std::map<int, Test> tmap;
tmap.try_emplace(10, 10, 10);


But there is no try_emplace for std::multimap<int, Test>, so piecewise_construct is still needed.



Is there a technical reason for this?







c++ c++17






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Dec 14 '18 at 15:15









Boann

36.7k1287121




36.7k1287121










asked Dec 14 '18 at 1:05









Lei Yu

634




634








  • 2




    std::multimap does not need try_emplace as it always inserts, so emplace is enough.
    – Slava
    Dec 14 '18 at 1:26










  • I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
    – Lei Yu
    Dec 14 '18 at 5:46














  • 2




    std::multimap does not need try_emplace as it always inserts, so emplace is enough.
    – Slava
    Dec 14 '18 at 1:26










  • I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
    – Lei Yu
    Dec 14 '18 at 5:46








2




2




std::multimap does not need try_emplace as it always inserts, so emplace is enough.
– Slava
Dec 14 '18 at 1:26




std::multimap does not need try_emplace as it always inserts, so emplace is enough.
– Slava
Dec 14 '18 at 1:26












I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
– Lei Yu
Dec 14 '18 at 5:46




I see, but it's really handy if piecewise_construct can be get rid of for std::multimap
– Lei Yu
Dec 14 '18 at 5:46












2 Answers
2






active

oldest

votes


















14















is there a technical reason for this?




Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.



As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.





Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:



template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
return map.emplace(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(key)),
std::forward_as_tuple(std::forward<Args>(args)...));
}


Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.






share|improve this answer



















  • 1




    Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
    – leftaroundabout
    Dec 14 '18 at 10:36






  • 1




    @leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










  • @LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
    – leftaroundabout
    Dec 14 '18 at 14:14








  • 1




    @leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:15





















6














It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):




The existing interface of unique-keyed map containers (std::map,
std::unordered_map) is slightly underspecified, which makes certain
container mutations more complicated to write and error-prone than
necessary
. This paper describes new member function templates to
fill this gap.



The justification and rationale for the new interface are given in
N3873. The initial reaction to N3873 in Issaquah was that the existing
map interfaces should be fixed rather than adding new interfaces. We
explored this idea in N4006 in Rapperswil and decided that the
original proposal was preferable (with some name changes). This paper
only summarises the proposed extension without repeating the original
discussion. We only restate the motivating code snippet here for
motivation:



std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr); // ??? (may or may not fire)






share|improve this answer



















  • 1




    thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
    – Lei Yu
    Dec 14 '18 at 5:43










  • @LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
    – Slava
    Dec 14 '18 at 13:34










  • @LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08













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',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
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%2f53772218%2fwhy-is-try-emplace-not-implemented-for-stdmultimap%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









14















is there a technical reason for this?




Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.



As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.





Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:



template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
return map.emplace(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(key)),
std::forward_as_tuple(std::forward<Args>(args)...));
}


Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.






share|improve this answer



















  • 1




    Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
    – leftaroundabout
    Dec 14 '18 at 10:36






  • 1




    @leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










  • @LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
    – leftaroundabout
    Dec 14 '18 at 14:14








  • 1




    @leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:15


















14















is there a technical reason for this?




Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.



As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.





Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:



template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
return map.emplace(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(key)),
std::forward_as_tuple(std::forward<Args>(args)...));
}


Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.






share|improve this answer



















  • 1




    Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
    – leftaroundabout
    Dec 14 '18 at 10:36






  • 1




    @leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










  • @LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
    – leftaroundabout
    Dec 14 '18 at 14:14








  • 1




    @leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:15
















14












14








14







is there a technical reason for this?




Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.



As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.





Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:



template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
return map.emplace(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(key)),
std::forward_as_tuple(std::forward<Args>(args)...));
}


Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.






share|improve this answer















is there a technical reason for this?




Yes. The purpose of try_emplace() is to not do anything if the key already exists in the map. But for std::{unordered_,}multi{map,set}, you can have multiple values for each key. That is, indeed, the point of these containers: to have multiple values for a given key.



As a result, try_emplace() cannot fail for these containers - so it would be confusing and pointless to provide such a function.





Based on the comments, it seems that the motivation is just the part of try_emplace() that makes it easier to emplace a value. You can write a helper function for that:



template <typename Map, typename Key, typename... Args>
auto emplace_value(Map& map, Key&& key, Args&&... args) {
return map.emplace(std::piecewise_construct,
std::forward_as_tuple(std::forward<Key>(key)),
std::forward_as_tuple(std::forward<Args>(args)...));
}


Which would let you write emplace_value(tmap, 10, 10, 10), even for {unordered_,}multimap.







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 14 '18 at 14:39

























answered Dec 14 '18 at 1:33









Barry

177k18304559




177k18304559








  • 1




    Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
    – leftaroundabout
    Dec 14 '18 at 10:36






  • 1




    @leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










  • @LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
    – leftaroundabout
    Dec 14 '18 at 14:14








  • 1




    @leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:15
















  • 1




    Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
    – leftaroundabout
    Dec 14 '18 at 10:36






  • 1




    @leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










  • @LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
    – leftaroundabout
    Dec 14 '18 at 14:14








  • 1




    @leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:15










1




1




Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
– leftaroundabout
Dec 14 '18 at 10:36




Well, one might still want to insert some elements only in case the key isn't present already, even in a multimap. Just it's probably not common enough to warrant having that method in the standard library.
– leftaroundabout
Dec 14 '18 at 10:36




1




1




@leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
– Lightness Races in Orbit
Dec 14 '18 at 14:08




@leftaroundabout Yeah, they can still do that, but as it's a sign that you may be using the wrong container, the standard prefers not to give us a feature to do it. Just like how you can't arbitrarily arithmetise non-random-access iterators -- if you really feel the need then there's std::next but the standard won't make it trivial for you because it doesn't think you should be doing it usually.
– Lightness Races in Orbit
Dec 14 '18 at 14:08












@LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
– leftaroundabout
Dec 14 '18 at 14:14






@LightnessRacesinOrbit not sure that's a good analogy, because random jumps of sequential iterators can be much more expensive than for vector iterators, so making them easy would be a significant performance risk. Whereas I don't see reason why try_emplace would be much slower for any multimap implementation, than it is on std::map.
– leftaroundabout
Dec 14 '18 at 14:14






1




1




@leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
– Lightness Races in Orbit
Dec 14 '18 at 14:15






@leftaroundabout Meh, suppose you're right. Still, I think the general attitude that led to both choices is ultimately the same, despite the difference in practical cost if you go ahead anyway. In fact I've always been rubbed a little wrong when people use only "performance" as an argument for why sequential iterators can't be +='d; there's a strong semantic argument too. It's to stop you writing "bad code", after all, and raw performance isn't everything.
– Lightness Races in Orbit
Dec 14 '18 at 14:15















6














It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):




The existing interface of unique-keyed map containers (std::map,
std::unordered_map) is slightly underspecified, which makes certain
container mutations more complicated to write and error-prone than
necessary
. This paper describes new member function templates to
fill this gap.



The justification and rationale for the new interface are given in
N3873. The initial reaction to N3873 in Issaquah was that the existing
map interfaces should be fixed rather than adding new interfaces. We
explored this idea in N4006 in Rapperswil and decided that the
original proposal was preferable (with some name changes). This paper
only summarises the proposed extension without repeating the original
discussion. We only restate the motivating code snippet here for
motivation:



std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr); // ??? (may or may not fire)






share|improve this answer



















  • 1




    thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
    – Lei Yu
    Dec 14 '18 at 5:43










  • @LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
    – Slava
    Dec 14 '18 at 13:34










  • @LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08


















6














It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):




The existing interface of unique-keyed map containers (std::map,
std::unordered_map) is slightly underspecified, which makes certain
container mutations more complicated to write and error-prone than
necessary
. This paper describes new member function templates to
fill this gap.



The justification and rationale for the new interface are given in
N3873. The initial reaction to N3873 in Issaquah was that the existing
map interfaces should be fixed rather than adding new interfaces. We
explored this idea in N4006 in Rapperswil and decided that the
original proposal was preferable (with some name changes). This paper
only summarises the proposed extension without repeating the original
discussion. We only restate the motivating code snippet here for
motivation:



std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr); // ??? (may or may not fire)






share|improve this answer



















  • 1




    thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
    – Lei Yu
    Dec 14 '18 at 5:43










  • @LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
    – Slava
    Dec 14 '18 at 13:34










  • @LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08
















6












6








6






It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):




The existing interface of unique-keyed map containers (std::map,
std::unordered_map) is slightly underspecified, which makes certain
container mutations more complicated to write and error-prone than
necessary
. This paper describes new member function templates to
fill this gap.



The justification and rationale for the new interface are given in
N3873. The initial reaction to N3873 in Issaquah was that the existing
map interfaces should be fixed rather than adding new interfaces. We
explored this idea in N4006 in Rapperswil and decided that the
original proposal was preferable (with some name changes). This paper
only summarises the proposed extension without repeating the original
discussion. We only restate the motivating code snippet here for
motivation:



std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr); // ??? (may or may not fire)






share|improve this answer














It is not necessary since for multimap case since there is no unique key, try_emplace would never fail. The rational for adding try_emplace to map was all the error prone code needed to deal with the case that key already exists, see the proposal n4279 (emphasis mine):




The existing interface of unique-keyed map containers (std::map,
std::unordered_map) is slightly underspecified, which makes certain
container mutations more complicated to write and error-prone than
necessary
. This paper describes new member function templates to
fill this gap.



The justification and rationale for the new interface are given in
N3873. The initial reaction to N3873 in Issaquah was that the existing
map interfaces should be fixed rather than adding new interfaces. We
explored this idea in N4006 in Rapperswil and decided that the
original proposal was preferable (with some name changes). This paper
only summarises the proposed extension without repeating the original
discussion. We only restate the motivating code snippet here for
motivation:



std::map<std::string, std::unique_ptr<Foo>> m;
m["foo"] = nullptr;

auto ptr = std::make_unique_ptr<Foo>;
auto res = m.emplace("foo", std::move(ptr));

assert(ptr); // ??? (may or may not fire)







share|improve this answer














share|improve this answer



share|improve this answer








edited Dec 14 '18 at 14:10

























answered Dec 14 '18 at 1:32









Shafik Yaghmour

125k23322532




125k23322532








  • 1




    thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
    – Lei Yu
    Dec 14 '18 at 5:43










  • @LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
    – Slava
    Dec 14 '18 at 13:34










  • @LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08
















  • 1




    thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
    – Lei Yu
    Dec 14 '18 at 5:43










  • @LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
    – Slava
    Dec 14 '18 at 13:34










  • @LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
    – Lightness Races in Orbit
    Dec 14 '18 at 14:08










1




1




thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
– Lei Yu
Dec 14 '18 at 5:43




thanks for the explanation, but it's kind of against intuition that ptr would still be valid after std::move is called on it.
– Lei Yu
Dec 14 '18 at 5:43












@LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
– Slava
Dec 14 '18 at 13:34




@LeiYu std::move does not modify the object by itself it just makes it possible, you need to change your intuition. For example auto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 ); - p1 is not affected
– Slava
Dec 14 '18 at 13:34












@LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
– Lightness Races in Orbit
Dec 14 '18 at 14:08






@LeiYu Only because std::move is the wrong name for what it does! (Important people have since admitted this.) You have indeed found a perfect example of why that is.
– Lightness Races in Orbit
Dec 14 '18 at 14:08




















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53772218%2fwhy-is-try-emplace-not-implemented-for-stdmultimap%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

"Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

Alcedinidae

Origin of the phrase “under your belt”?