5.9 KiB
Problem with
is_writable and is_swappable in N1550
- Author
- David Abrahams and Jeremy Siek
- Contact
- dave@boost-consulting.com, jsiek@osl.iu.edu
- Organization
- Boost Consulting, Indiana University Bloomington
- Copyright
- Copyright David Abrahams, Jeremy Siek 2003. Use, modification and distribution is subject to the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Table of Contents
Introduction
The is_writable and is_swappable traits
classes in N1550
provide a mechanism for determining at compile time if an iterator type
is a model of the new Writable Iterator and Swappable Iterator concepts,
analogous to iterator_traits<X>::iterator_category
for the old iterator concepts. For backward compatibility,
is_writable and is_swappable not only work
with new iterators, but they also are intended to work for old iterators
(iterators that meet the requirements for one of the iterator concepts
in the current standard). In the case of old iterators, the writability
and swapability is deduced based on the iterator_category
and also the reference type. The specification for this
deduction gives false positives for forward iterators that have
non-assignable value types.
To review, the part of the is_writable trait definition
which applies to old iterators is:
if (cat is convertible to output_iterator_tag)
return true;
else if (cat is convertible to forward_iterator_tag
and iterator_traits<Iterator>::reference is a
mutable reference)
return true;
else
return false;
Suppose the value_type of the iterator It
has a private assignment operator:
class B {
public:
...
private:
B& operator=(const B&);
};
and suppose the reference type of the iterator is
B&. In that case,
is_writable<It>::value will be true when in fact
attempting to write into B will cause an error.
The same problem applies to is_swappable.
Proposed Resolution
Remove the
is_writableandis_swappabletraits, and remove the requirements in the Writable Iterator and Swappable Iterator concepts that require their models to support these traits.Change the
is_readablespecification to be:is_readable<X>::typeistrue_typeif the result type ofX::operator*is convertible toiterator_traits<X>::value_typeand isfalse_typeotherwise. Also,is_readableis required to satisfy the requirements for the UnaryTypeTrait concept (defined in the type traits proposal).Remove the requirement for support of the
is_readabletrait from the Readable Iterator concept.Remove the
iterator_tagclass.Change the specification of
traversal_categoryto:traversal-category(Iterator) = let cat = iterator_traits<Iterator>::iterator_category if (cat is convertible to incrementable_iterator_tag) return cat; // Iterator is a new iterator else if (cat is convertible to random_access_iterator_tag) return random_access_traversal_tag; else if (cat is convertible to bidirectional_iterator_tag) return bidirectional_traversal_tag; else if (cat is convertible to forward_iterator_tag) return forward_traversal_tag; else if (cat is convertible to input_iterator_tag) return single_pass_iterator_tag; else if (cat is convertible to output_iterator_tag) return incrementable_iterator_tag; else return null_category_tag;
Rationale
- There are two reasons for removing
is_writableandis_swappable. The first is that we do not know of a way to fix the specification so that it gives the correct answer for all iterators. Second, there was only a weak motivation for havingis_writableandis_swappablethere in the first place. The main motivation was simply uniformity: we have tags for the old iterator categories so we should have tags for the new iterator categories. While having tags and the capability to dispatch based on the traversal categories is often used, we see less of a need for dispatching based on writability and swappability, since typically algorithms that need these capabilities have no alternative if they are not provided. - We discovered that the
is_readabletrait can be implemented using only the iterator type itself and itsvalue_type. Therefore we remove the requirement foris_readablefrom the Readable Iterator concept, and change the definition ofis_readableso that it works for any iterator type. - The purpose of the
iterator_tagclass was to bundle the traversal and access category tags into theiterator_categorytypedef. Withis_writableandis_swappablegone, andis_readableno longer in need of special hints, there is no reason for iterators to provide information about the access capabilities of an iterator. Thus there is no need for theiterator_tag. The traversal tag can be directly used for theiterator_category. If a new iterator is intended to be backward compatible with old iterator concepts, a tag type that is convertible to both one of the new traversal tags and also to an old iterator tag can be created and use for theiterator_category. - The changes to the specification of
traversal_categoryare a direct result of the removal ofiterator_tag.