Interface of std::map's erase member functions

A

Angus Leeming

Dinkumware's online STL reference http://tinyurl.com/3es52 declares
std::map's overloaded erase member functions to have the interface:

map::erase

iterator erase(iterator where);
iterator erase(iterator first, iterator last);
size_type erase(const Key& keyval);

Ie, the first two functions above have the same interface as
std::vector returning an iterator

My copy of gcc's routines declares that the interface is:

void erase(iterator where);
void erase(iterator first, iterator last);
size_type erase(const Key& keyval);

As does the SGI online docs at http://tinyurl.com/u2uy

Am I correct in saying that Dinkumware have got it wrong?
Regards,
Angus
 
T

tom_usenet

Dinkumware's online STL reference http://tinyurl.com/3es52 declares
std::map's overloaded erase member functions to have the interface:

map::erase

iterator erase(iterator where);
iterator erase(iterator first, iterator last);
size_type erase(const Key& keyval);

Ie, the first two functions above have the same interface as
std::vector returning an iterator

My copy of gcc's routines declares that the interface is:

void erase(iterator where);
void erase(iterator first, iterator last);
size_type erase(const Key& keyval);

As does the SGI online docs at http://tinyurl.com/u2uy

Am I correct in saying that Dinkumware have got it wrong?

Yes - their signature isn't conforming. However, it is difficult to
detect this problem with conforming code, since you can't rely on any
particular signature for non-virtual standard library member
functions. Use the post increment technique to make your code
conforming.
Not:
i = m.erase(i); //non-conforming, relies on Dinkumware extension
but the roughly equivalent:
m.erase(i++); //conforming.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
A

Angus Leeming

tom_usenet said:
Yes - their signature isn't conforming. However, it is difficult to
detect this problem with conforming code, since you can't rely on
any particular signature for non-virtual standard library member
functions. Use the post increment technique to make your code
conforming.

Thanks Tom.

Actually, I'm trying to write a single lambda function wrapper
for all of the stl containers' erase signatures.

I guess something tasting like the boost lambda library will
make it into some future standard, so the code below isn't totally
off topic. Just mostly ;-)

Angus


struct erase {

/*
This mouthful can differentiate between the generic erase functions
(Container == deque, list, vector) and that
specific to the two map-types, std::map and std::multimap.

iterator Container::erase(iterator where);
iterator Container::erase(iterator first, iterator last);

size_type Map::erase(const Key& keyval);
void Map::erase(iterator where);
void Map::erase(iterator first, iterator last);

*/
template <typename T,
typename Arg1,
typename Arg2 = nil_t>
struct result
{
typedef
boost::mpl::apply_if<
boost::mpl::eek:r_<
is_std_map<T>
, is_std_multimap<T> >
stage_1;

typedef typename
boost::mpl::apply_if<
boost::mpl::and_<
boost::is_same<Arg1, typename key_type_of<Arg1>::type>
, boost::is_same<Arg2, nil_t> >
type;
};

template <typename T, typename Arg1>
typename result<T, Arg1>::type
operator()(T & c, Arg1 const & arg1) const
{
return c.erase(arg1);
}

template <typename T>
typename result<T, typename T::iterator, typename T::iterator>::type
operator()(T & c,
typename T::iterator const & from,
typename T::iterator const & to) const
{
return c.erase(from, to);
}
};
 
J

Jonathan Turkanis

tom_usenet said:
Yes - their signature isn't conforming. However, it is difficult to
detect this problem with conforming code, since you can't rely on any
particular signature for non-virtual standard library member
functions.

Doesn't this do the trick?

void f(std::map<int, int>& m)
{
std::map<int, int>::iterator it = m.begin();
if (it != m.end()) return m.erase(it);
}

This should compile only if map::erase returns void.

Jonathan
 
T

tom_usenet

Doesn't this do the trick?

void f(std::map<int, int>& m)
{
std::map<int, int>::iterator it = m.begin();
if (it != m.end()) return m.erase(it);
}

This should compile only if map::erase returns void.

True, I hadn't thought of that, but who ever returns a void value from
a void function? I suppose I should rephrase - it is unlikely that
conforming code will ever be affected by the invalid return type, but
it is possible.

The problem is that Dinkumware doesn't want to break code written to
one of their old, pre-standard libraries that also returned the
iterator, but wasn't non-conforming since there was no standard to
conform to.

Tom

C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
 
H

Howard Hinnant

tom_usenet said:
True, I hadn't thought of that, but who ever returns a void value from
a void function? I suppose I should rephrase - it is unlikely that
conforming code will ever be affected by the invalid return type, but
it is possible.

The problem is that Dinkumware doesn't want to break code written to
one of their old, pre-standard libraries that also returned the
iterator, but wasn't non-conforming since there was no standard to
conform to.

Fwiw, this is LWG issue 130:

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/lwg-active.html#130

Years ago it was voted as "not a defect" by the LWG. But the issue has
recently been reopened (at my request) in a new light: Ok, so it was an
intentional design decision for C++98. But for C++0X would it be better
to change the return type of these functions to iterator?

Several of the "NAD" defect reports are now being reexamined within the
context of C++0X.

-Howard
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,020
Latest member
GenesisGai

Latest Threads

Top