Prev: The D Programming Language
Next: CRTP question
From: Alberto Ganesh Barbati on 23 Nov 2006 07:04 Terry G ha scritto: > > Sorry, I've been guilty of that on several posts recently. I'm in a hurry. > Here's some runnable code that illustrates my point. > It contains my previous code, that used a vector<MyType>, where MyType is > uint8_t. > I wanted to allow the user to use the container of her choice and a > reasonable type too. > Thats the "current" version. > Then, I show the code that I wish would work, but it doesn't because > value_type for back_inserter is void. > > <code snipped>> > Much better! ;-) Maybe this could be a solution: template <class T> struct true_value_type { typedef typename std::iterator_traits<T>::value_type type; }; template <class T> struct true_value_type<std::back_insert_iterator<T> > { typedef typename T::value_type type; }; then you just use template <class OutIter> OutIter CopyOutWish(OutIter dst, const uint8_t* src, size_t size, unsigned count) { typedef typename true_value_type<OutIter>::type DstType; /* */ } HTH, Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Terry G on 23 Nov 2006 13:40 Ganesh suggests: > template <class T> > struct true_value_type > { > typedef typename std::iterator_traits<T>::value_type type; > }; > > template <class T> > struct true_value_type<std::back_insert_iterator<T> > > { > typedef typename T::value_type type; > }; > > then you just use > > template <class OutIter> > OutIter CopyOutWish(OutIter dst, const uint8_t* src, size_t size, > unsigned count) > { > typedef typename true_value_type<OutIter>::type DstType; > /* */ > } I like that and will use it. Thanks. I imagine that this will become more of a problem for more people in the near future. More people are caring about such things. If value_type is inappropriate for this, should another standard iterator trait be defined for this purpose? I would have called such a trait "value_type". Apparently, "value_type" should have been named "pointee_type". Then, I wouldn't have been confused. How about "deref_type"? I'm in a hurry again, but this would be cool.. typedef typeof(*OutIter) OutType; Something like typeof() would make a whole lot of clever template programming easier. Gotta run! I'm late for Thanksgiving dinner. terry -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Gabriel Dos Reis on 23 Nov 2006 18:42 Howard Hinnant <howard.hinnant(a)gmail.com> writes: | 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); This is not meant to pick on you. But, I don't want to generic code like that. And I would not want C++ programmers to get exposed to that kind of code as the sort of things people write in generic programmng :-) I would like to write a generic format() that does not require a cast (whether static or not). -- Gabriel Dos Reis gdr(a)integrable-solutions.net [ 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 23 Nov 2006 20:04 Terry G ha scritto: > If value_type is inappropriate for this, should another standard iterator > trait be defined for this purpose? > I would have called such a trait "value_type". > Apparently, "value_type" should have been named "pointee_type". > Then, I wouldn't have been confused. > How about "deref_type"? In the standard library, "value_type" is a type that can hold the result of *it. It sounds good to me and it's consistent with the value_type typedef of containers (in the sense that the value_type of a container and of its iterators is the same except possibly for const qualifiers). I find it good that value_type is void for "pure" output iterators because the expression "*it" is not intended to have a "storable" value. In standardese: "The only valid use of an operator* is on the left side of the assignment statement." So I find value_type to be properly defined, useful and correctly named. About "your" trait, notice that there may be output iterators for which there is no unique way to define it. The standard requires that "*it = o" is defined for some "o", but does *not* require that there must be exactly *one type* of "o" that can be used in such expression. For example it is quite easy to write one ostream_iterator-like class that is able to write onto a stream any type for which operator<< is properly overloaded. So in order to define your trait you have to restrict to a subset of output iterators and this automatically makes the trait less useful. How to call it? The first two names that come to my mind are source_type and source_value_type. > I'm in a hurry again, but this would be cool.. > > typedef typeof(*OutIter) OutType; > > Something like typeof() would make a whole lot of clever template > programming easier. They're working on it and it seems there's good chance that it will be included in the next revision of C++. The name is probably going to declspec, not typeof. Notice that in the case of "pure" output iterators declspec(*it) is still useless, because it's the type on right hand side of the "=" that you are interested into, but *it lies on the left side and is probably going to be some uninteresting proxy object. Ganesh -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ]
From: Terry G on 23 Nov 2006 23:00
> Terry G ha scritto: >> >> A question: why do you prefer static_cast<value_type>(val) >> instead of using the function-like form: value_type(val)? >> Is there any significant difference? >> > Ganesh replied > The function-like form with one argument is actually equivalent to the > C-style cast (value_type)(val) so it could apply either a static_cast or > a reinterpret_cast (plus an additional const_cast). Terry had a spaz! What!? I thought the function-style cast was equivalent to static_cast. I read the C++ spec and its not yet clear to me. It seems that for built-in types, type(x) is equivalent to (type) x. That's scary. But what about for non-built-in types. Is type(x) equivalent to static_cast<type>(x)? Should I stop using function-style casts altogether? terry -- [ See http://www.gotw.ca/resources/clcm.htm for info about ] [ comp.lang.c++.moderated. First time posters: Do this! ] |