Re: Why no std::back_insert_iterator::value_type?
In article <4qV8h.51940$uv5.351593@twister1.libero.it>,
Alberto Ganesh Barbati <AlbertoBarbati@libero.it> wrote:
Terry G ha scritto:
Because back_inserter_iterator<> is an output iterator but not an input
iterator. value_type, which is defined as the type able to hold the
value of the expression *it, makes sense only for input iterators.
What if I want to know what type *it will return?
The requirement of an output iterator says that the expression "*it = v"
is well-defined and does what it's supposed to do, but it's not said
what the expression "*it" is required to be and even if it can be used
in any way different from "*it = v". Therefore, defining value_type to
be void is a big warning sign that you shouldn't rely on the actual
type. It's like this for your own good. Why do you want to know?
Ganesh
PS: once we have decltype in the language, we could write decltype(*it),
but the question remains: what for?
I know why *I* want output iterators to have value_type. Because I want
to write generic code like:
template <class It>
It
format(char val, It first, It last)
{
typedef typename std::iterator_traits<It>::value_type value_type;
if (first == last)
throw format_error();
*first = static_cast<value_type>(val);
return ++first;
}
I.e. I don't want the return type of *it (which should be it::reference
anyway, and it is fine with me if *it returns void). I want a type such
that if I convert my value v to that type, I'm assured of a clean
assignment into the output iterator.
Note that I'm also wanting output iterators to be equality comparable.
In the case of back_insert_iterator, the following definitions would be
fine:
bool operator==(const back_insert_iterator&,
const back_insert_iterator&)
{return false;}
bool operator!=(const back_insert_iterator&,
const back_insert_iterator&)
{return true;}
With such changes I could safely format a char into any "iterator
delimited stream".
template <class Container>
class back_insert_iterator
{
protected:
Container* container;
public:
typedef Container container_type;
typedef output_iterator_tag iterator_category;
typedef typename container_type::value_type value_type;
typedef ptrdiff_t difference_type;
typedef typename container_type::pointer pointer;
typedef back_insert_iterator& reference;
explicit back_insert_iterator(Container& x) : container(&x) {}
back_insert_iterator& operator=(const value_type& value)
{container->push_back(value); return *this;}
back_insert_iterator& operator=(value_type&& value)
{container->push_back(std::move(value)); return *this;}
reference operator*() {return *this;}
reference operator++() {return *this;}
reference operator++(int) {return *this;}
friend bool operator==(const back_insert_iterator&,
const back_insert_iterator&) {return false;}
friend bool operator!=(const back_insert_iterator&,
const back_insert_iterator&) {return true;}
};
-Howard
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]