From: Brendan on
I'm trying to use a type that is moveable, but not copyable, in a
standard container, in this case an unordered_map. When I try to
insert it, I get complaints about a deleted copy constructor. I
thought that move only objects were supported in standard containers?

Here's my type:

struct session_t {
session_t() : fd(make_unique_fd(0)) {}
session_t(const session_t&) = delete;
session_t& operator=(const session_t&) = delete;
session_t(session_t&& session) : fd(move(session.fd)) {}
session_t& operator=(session_t&& other) {
if (this != &other) {
fd = move(other.fd);
}
return *this;
}

unique_fd fd;
};

typedef unordered_map<int, session_t> session_map;

Heres where the error pops up:
map.insert(make_pair(*session.fd, move(session)));

Testing on GCC 4.4

--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Daniel Krügler on
On 26 Apr., 10:52, Brendan <catph...(a)catphive.net> wrote:
> I'm trying to use a type that is moveable, but not copyable, in a
> standard container, in this case an unordered_map. When I try to
> insert it, I get complaints about a deleted copy constructor. I
> thought that move only objects were supported in standard containers?
>
> Here's my type:
>
> struct session_t {
> session_t() : fd(make_unique_fd(0)) {}
> session_t(const session_t&) = delete;
> session_t& operator=(const session_t&) = delete;
> session_t(session_t&& session) : fd(move(session.fd)) {}
> session_t& operator=(session_t&& other) {
> if (this != &other) {
> fd = move(other.fd);
> }
> return *this;
> }
>
> unique_fd fd;
> };
>
> typedef unordered_map<int, session_t> session_map;
>
> Heres where the error pops up:
> map.insert(make_pair(*session.fd, move(session)));

This should work. It should also work more directly
by writing

map.emplace(*session.fd, std::move(session));

instead.

> Testing on GCC 4.4

Even the most recent 4.5.0-1 trunk of gcc does not
properly handle this and does not recognize the
emplace member function. Same problem for std::map.
Looks like an incomplete implementation to me in
regard to the working draft.

HTH & Greetings from Bremen,

Daniel Kr�gler



--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Howard Hinnant on
On Apr 26, 4:52 am, Brendan <catph...(a)catphive.net> wrote:
> I'm trying to use a type that is moveable, but not copyable, in a
> standard container, in this case an unordered_map. When I try to
> insert it, I get complaints about a deleted copy constructor. I
> thought that move only objects were supported in standard containers?
>
> Here's my type:
>
> struct session_t {
> session_t() : fd(make_unique_fd(0)) {}
> session_t(const session_t&) = delete;
> session_t& operator=(const session_t&) = delete;
> session_t(session_t&& session) : fd(move(session.fd)) {}
> session_t& operator=(session_t&& other) {
> if (this != &other) {
> fd = move(other.fd);
> }
> return *this;
> }
>
> unique_fd fd;
>
> };
>
> typedef unordered_map<int, session_t> session_map;
>
> Heres where the error pops up:
> map.insert(make_pair(*session.fd, move(session)));
>
> Testing on GCC 4.4

Although your unique_fd is not defined, I believe your test case
should work, using the insert member defined in [map.modifiers]. I
suspect, but do not know, that this member is simply not implemented
yet for GCC 4.4.

-Howard


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Brian on
On Apr 26, 11:50 am, Daniel Kr�gler <daniel.krueg...(a)googlemail.com>
wrote:
> On 26 Apr., 10:52, Brendan <catph...(a)catphive.net> wrote:
>
> > I'm trying to use a type that is moveable, but not copyable, in a
> > standard container, in this case an unordered_map. When I try to
> > insert it, I get complaints about a deleted copy constructor. I
> > thought that move only objects were supported in standard containers?
>
> > Here's my type:
>
> > struct session_t {
> > session_t() : fd(make_unique_fd(0)) {}
> > session_t(const session_t&) = delete;
> > session_t& operator=(const session_t&) = delete;
> > session_t(session_t&& session) : fd(move(session.fd)) {}
> > session_t& operator=(session_t&& other) {
> > if (this != &other) {
> > fd = move(other.fd);
> > }
> > return *this;
> > }
>
> > unique_fd fd;
> > };
>
> > typedef unordered_map<int, session_t> session_map;
>
> > Heres where the error pops up:
> > map.insert(make_pair(*session.fd, move(session)));
>
> This should work. It should also work more directly
> by writing
>
> map.emplace(*session.fd, std::move(session));
>
> instead.
>

I've been thinking about this topic recently and am wondering
about the "more directly" there. Does the emplace version
have, at least theoretically, an efficiency advantage over the
insert version? TIA.


Brian Wood
http://webEbenezer.net
(651) 251-9384


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

From: Mathias Gaunard on
On 29 avr, 08:52, Brian <c...(a)mailvault.com> wrote:

> I've been thinking about this topic recently and am wondering
> about the "more directly" there. Does the emplace version
> have, at least theoretically, an efficiency advantage over the
> insert version? TIA.

With emplace, you construct the pair directly into the container,
while otherwise you construct a temporary that you move-construct
later into the container.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]