Topic: Defect report: std::map not a container
Author: pdimov@techno-link.com
Date: 2000/11/09 Raw View
In article <hinnant-0811002053460001@ith3-420.twcny.rr.com>,
hinnant@anti-spam_metrowerks.com (Howard Hinnant) wrote:
> In article <8ubmrm$ifl$1@nnrp1.deja.com>, pdimov@techno-link.com
wrote:
>
> | list::assign(first, last) is defined (23.2.2.1/7) as being
equivalent to
> |
> | erase(begin(), end()); insert(begin(), first, last);
> |
> | so I think that it can't use T::operator= to perform the
assignment; a
> | destructor/copy-constructor sequence is implied. The other
list::assign
> | overload has a similar "Effects" clause.
> |
> | Perhaps I interpret the "Effects" clause too strictly?
>
> I hope so. I would like to think there is a big "as if" in there
> (especially since assignable IS currently required). I agree it can
be
> quite a large gray area as to when and how far "as if" will take
you. But
> taking advantage of assignable can be a significant performance
advantage
> over erase/insert.
I think that this issue probably deserves a DR of its own. "As if", in
the usual sense, doesn't apply... no "as if" rule can justify replacing
an erase/insert sequence (that is defined to invoke size() destructors
(23.2.2.3/5) and last - first copy constructors (23.2.2.3/2)) with a
loop that calls T::op=. Especially if some T operation throws an
exception. Consider also the fact that if insert'ing a single element
throws, the insert() is guaranteed to have no effect (23.1/10).
The "as if" rule, however, may be legitimately used to avoid
deallocating and reallocating memory, minimizing the performance loss.
> | In any event, wouldn't it be possible to require that T be
Assignable
> | only if the methods in question are actually used? (An explicit
> | instantiation of std::list<T> would be considered an 'use'.)
>
> Throw in assign and you've got a deal. ;-)
Oh, I already did - "methods in question". :-)
--
Peter Dimov
Multi Media Ltd.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: "Peter Dimov" <pdimov@mmltd.net>
Date: 2000/11/07 Raw View
[Moderator's note: this defect report has been
forwarded to the C++ committee. -moderator(fjh).]
Section: 23.1 [lib.container.requirements], 23.3.1 [lib.map], 23.3.2
[lib.multimap]
23.1/3 states that the objects stored in a container must be Assignable.
23.3.1/2 states that map satisfies all requirements for a container, while
in the same time defining value_type as pair<const Key, T> - a type that is
not Assignable.
It should be noted that there exists a valid and non-contradictory
interpretation of the current text. The wording in 23.1/3 avoids to mention
value_type, referring instead to "objects stored in a container." One might
argue that map does not store objects of type map::value_type, but of
map::mapped_type instead, and that the Assignable requirement applies to
map::mapped_type, not map::value_type.
However, this makes map a special case (other containers store objects of
type value_type) and the Assignable requirement is needlessly restrictive in
general.
For example, the proposed resolution of active library issue #103 is to make
set::iterator a constant iterator; this means that no set operations can
exploit the fact that the stored objects are Assignable.
Proposed resolution:
Remove the requirement that the objects stored in a container be Assignable
from 23.1/3 and reintroduce it on a case by case basis (for vector and
deque.)
Rationale:
list, set, multiset, map, multimap are able to store non-Assignables.
--
Peter Dimov
Multi Media Ltd.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
Author: hinnant@anti-spam_metrowerks.com (Howard Hinnant)
Date: 2000/11/07 Raw View
In article <8u9agl$ont$1@weber.techno-link.com>, "Peter Dimov"
<pdimov@mmltd.net> wrote:
| [Moderator's note: this defect report has been
| forwarded to the C++ committee. -moderator(fjh).]
|
| Section: 23.1 [lib.container.requirements], 23.3.1 [lib.map], 23.3.2
| [lib.multimap]
|
| 23.1/3 states that the objects stored in a container must be Assignable.
| 23.3.1/2 states that map satisfies all requirements for a container, while
| in the same time defining value_type as pair<const Key, T> - a type that is
| not Assignable.
|
| It should be noted that there exists a valid and non-contradictory
| interpretation of the current text. The wording in 23.1/3 avoids to mention
| value_type, referring instead to "objects stored in a container." One might
| argue that map does not store objects of type map::value_type, but of
| map::mapped_type instead, and that the Assignable requirement applies to
| map::mapped_type, not map::value_type.
|
| However, this makes map a special case (other containers store objects of
| type value_type) and the Assignable requirement is needlessly restrictive in
| general.
|
| For example, the proposed resolution of active library issue #103 is to make
| set::iterator a constant iterator; this means that no set operations can
| exploit the fact that the stored objects are Assignable.
|
| Proposed resolution:
|
| Remove the requirement that the objects stored in a container be Assignable
| from 23.1/3 and reintroduce it on a case by case basis (for vector and
| deque.)
|
| Rationale:
|
| list, set, multiset, map, multimap are able to store non-Assignables.
I object to list being included in this group, at least if
list<T>::operator= or list<T>::assign is instantiated. The assignable
properties of T can be put to good use in these methods.
-Howard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: pdimov@techno-link.com
Date: 2000/11/08 Raw View
In article <hinnant-0711001656520001@ith3-43f.twcny.rr.com>,
hinnant@anti-spam_metrowerks.com (Howard Hinnant) wrote:
> In article <8u9agl$ont$1@weber.techno-link.com>, "Peter Dimov"
> <pdimov@mmltd.net> wrote:
>
> | list, set, multiset, map, multimap are able to store non-
Assignables.
>
> I object to list being included in this group, at least if
> list<T>::operator= or list<T>::assign is instantiated. The assignable
> properties of T can be put to good use in these methods.
list::assign(first, last) is defined (23.2.2.1/7) as being equivalent to
erase(begin(), end()); insert(begin(), first, last);
so I think that it can't use T::operator= to perform the assignment; a
destructor/copy-constructor sequence is implied. The other list::assign
overload has a similar "Effects" clause.
Perhaps I interpret the "Effects" clause too strictly?
For list::operator=, I agree; it's possible to exploit the Assignable
properties of T. I'm not sure how such an implementation can be made
exception-safe, provided that this is a design goal, of course.
In any event, wouldn't it be possible to require that T be Assignable
only if the methods in question are actually used? (An explicit
instantiation of std::list<T> would be considered an 'use'.)
--
Peter Dimov
Multi Media Ltd.
Sent via Deja.com http://www.deja.com/
Before you buy.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]
Author: hinnant@anti-spam_metrowerks.com (Howard Hinnant)
Date: 2000/11/09 Raw View
In article <8ubmrm$ifl$1@nnrp1.deja.com>, pdimov@techno-link.com wrote:
| list::assign(first, last) is defined (23.2.2.1/7) as being equivalent to
|
| erase(begin(), end()); insert(begin(), first, last);
|
| so I think that it can't use T::operator= to perform the assignment; a
| destructor/copy-constructor sequence is implied. The other list::assign
| overload has a similar "Effects" clause.
|
| Perhaps I interpret the "Effects" clause too strictly?
I hope so. I would like to think there is a big "as if" in there
(especially since assignable IS currently required). I agree it can be
quite a large gray area as to when and how far "as if" will take you. But
taking advantage of assignable can be a significant performance advantage
over erase/insert.
| For list::operator=, I agree; it's possible to exploit the Assignable
| properties of T. I'm not sure how such an implementation can be made
| exception-safe, provided that this is a design goal, of course.
It is quite easy to give it the weak guarantee. To give it the strong
guarantee you spend twice the memory - which your clients may or may not
like. The erase/insert sequence specifies that only the weak guarantee is
in effect. If clients want a strong guarantee assign they can build one.
But they can't necessarily build a less expensive weak guarantee assign:
template <class Container>
void my_strong_assign(Container& x, const Container& y)
{
Container temp(y);
x.swap(temp);
}
| In any event, wouldn't it be possible to require that T be Assignable
| only if the methods in question are actually used? (An explicit
| instantiation of std::list<T> would be considered an 'use'.)
Throw in assign and you've got a deal. ;-)
-Howard
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://www.research.att.com/~austern/csc/faq.html ]
[ Note that the FAQ URL has changed! Please update your bookmarks. ]