Re: Why no std::back_insert_iterator::value_type?
In article
<howard.hinnant-BBDDCE.12010822112006@syrcnyrdrs-02-ge0.nyroc.rr.com>,
Howard Hinnant <howard.hinnant@gmail.com> wrote:
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;
well [N2134=06-0204 ]
24.4.2.1 Class template back_insert_iterator
namespace std {
template <class Container>
class back_insert_iterator :
public iterator<output_iterator_tag,void,void,void,void>
{
protected:
Container* container;
public:
typedef Container container_type;
// ,,,
};
template <class It,class Tag>
struct ValueType
{
typedef typename std::iterator_traits<It>::value_type type;
};
template <class It>
struct ValueType<It,std::input_iterator_tag>
{
typedef typename It::container_type::value_type type;
};
template <class It>
It format(char val,It first,It last)
{
typedef ValueType<It>::type value_type;
// ,,,
}
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]