Why is try_emplace not implemented for std::multimap?
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
add a comment |
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
2
std::multimap
does not needtry_emplace
as it always inserts, soemplace
is enough.
– Slava
Dec 14 '18 at 1:26
I see, but it's really handy if piecewise_construct can be get rid of forstd::multimap
– Lei Yu
Dec 14 '18 at 5:46
add a comment |
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
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
c++ c++17
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 needtry_emplace
as it always inserts, soemplace
is enough.
– Slava
Dec 14 '18 at 1:26
I see, but it's really handy if piecewise_construct can be get rid of forstd::multimap
– Lei Yu
Dec 14 '18 at 5:46
add a comment |
2
std::multimap
does not needtry_emplace
as it always inserts, soemplace
is enough.
– Slava
Dec 14 '18 at 1:26
I see, but it's really handy if piecewise_construct can be get rid of forstd::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
add a comment |
2 Answers
2
active
oldest
votes
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
.
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'sstd::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 whytry_emplace
would be much slower for any multimap implementation, than it is onstd::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
add a comment |
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)
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
@LeiYustd::move
does not modify the object by itself it just makes it possible, you need to change your intuition. For exampleauto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 );
- p1 is not affected
– Slava
Dec 14 '18 at 13:34
@LeiYu Only becausestd::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
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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
.
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'sstd::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 whytry_emplace
would be much slower for any multimap implementation, than it is onstd::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
add a comment |
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
.
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'sstd::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 whytry_emplace
would be much slower for any multimap implementation, than it is onstd::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
add a comment |
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
.
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
.
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'sstd::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 whytry_emplace
would be much slower for any multimap implementation, than it is onstd::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
add a comment |
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'sstd::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 whytry_emplace
would be much slower for any multimap implementation, than it is onstd::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
add a comment |
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)
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
@LeiYustd::move
does not modify the object by itself it just makes it possible, you need to change your intuition. For exampleauto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 );
- p1 is not affected
– Slava
Dec 14 '18 at 13:34
@LeiYu Only becausestd::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
add a comment |
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)
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
@LeiYustd::move
does not modify the object by itself it just makes it possible, you need to change your intuition. For exampleauto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 );
- p1 is not affected
– Slava
Dec 14 '18 at 13:34
@LeiYu Only becausestd::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
add a comment |
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)
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)
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
@LeiYustd::move
does not modify the object by itself it just makes it possible, you need to change your intuition. For exampleauto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 );
- p1 is not affected
– Slava
Dec 14 '18 at 13:34
@LeiYu Only becausestd::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
add a comment |
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
@LeiYustd::move
does not modify the object by itself it just makes it possible, you need to change your intuition. For exampleauto p1 = std::unique_ptr<int>(); auto &&p2 = std::move( p1 );
- p1 is not affected
– Slava
Dec 14 '18 at 13:34
@LeiYu Only becausestd::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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
2
std::multimap
does not needtry_emplace
as it always inserts, soemplace
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