Prev: The D Programming Language
Next: CRTP question
From: Alberto Ganesh Barbati on 22 Nov 2006 06:40 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? -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Clark S. Cox III on 22 Nov 2006 10:32 Terry G wrote: >> 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? Who says that *it returns anything useful? (Hint, for output iterators like back_insert_iterator or insert_iterator, *it is not required to return anything that can be used in any way other than assigning to it) -- Clark S. Cox III clarkcox3(a)gmail.com [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Terry G on 22 Nov 2006 16:37 Ganesh wrote: > 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? > PS: once we have decltype in the language, we could write decltype(*it), > but the question remains: what for? What for? Uh.. well I'm probably trying to do a "bad thing", but... Say I have a template function template <class OutIter> OutIter CopyOut(OutIter iter) { // What type does user want? I.e. what is OutIter::value_type? // Some appropriate logic to output internal state to users container. } // CopyOut The idea is that I have some internal information that I want to give to my user. Previously, I just returned a vector<MyType>, forcing a container, a copy, and a type. I wanted to be more flexible, allowing the user to specify any convertible type, avoid an unnecessary copy, and let her pick whatever container. terry -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Alberto Ganesh Barbati on 22 Nov 2006 18:42 Terry G ha scritto: > Ganesh wrote: > > Say I have a template function > > template <class OutIter> > OutIter CopyOut(OutIter iter) { > // What type does user want? I.e. what is OutIter::value_type? > // Some appropriate logic to output internal state to users container. > } // CopyOut Fact is that OutIter::value_type may not (and usually does not) convey any useful information. Even decltype(*iter) is not going to provide useful information for "pure" output iterators, such as std::back_inserter_iterator. If fact, if you look at the definition of std::back_inserter_iterator, the type of *iter is... std::back_inserter_iterator itself! For another kind of output iterator it might have been any proxy class. > The idea is that I have some internal information that I want to give to my > user. Which kind of information are you thinking about? Could you be more precise? > Previously, I just returned a vector<MyType>, forcing a container, a copy, > and a type. Previously? I'm sorry but I can't follow you there. You did not post any "previous" code to refer to. How could you expect people to understand? > I wanted to be more flexible, allowing the user to specify any convertible > type, avoid an unnecessary copy, > and let her pick whatever container. Please provide us a *working* code snippet of what you have but you don't like and some (obviously not working, but hopefully clarifying) code of what you would like to have. Otherwise we (both you and I) are just losing our time. Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Howard Hinnant on 22 Nov 2006 18:56
In article <4qV8h.51940$uv5.351593(a)twister1.libero.it>, Alberto Ganesh Barbati <AlbertoBarbati(a)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! ] |