fho
fho

Reputation: 6798

Converting arrays in stl like copy

It's time for another 'how do i do this in c++ without loosing my grip'-question!

This time:

Considering the following code taken from cplusplus.com:

template<class InputIterator, class OutputIterator>
  OutputIterator copy ( InputIterator first, InputIterator last, OutputIterator result )
{
  while (first!=last) *result++ = *first++;
  return result;
}

Is there a way to cast *first to the type of *result?

In other words: is there a way to determine (at compiletime) the type of result?

Upvotes: 2

Views: 292

Answers (4)

James Kanze
James Kanze

Reputation: 209

The short answer is no. If OutputIterator is really an OutputIterator (e.g. an ostream_iterator), then: typename std::iterator_traits::value_type will be void, and in C++0x, decltype(*result) is likely to be OutputIterator. (So Armen's suggestion doesn't work in template code.)

And Tony's suggestion involving reinterpret_cast doesn't work either. In fact, it will break things that do work (e.g. when InputIterator is returning int, and OutputIterator wants double).

The only real answer is Oli's. Which is logical: what you really want to do is transform your data, not just copy it.

Upvotes: 1

Tony Delroy
Tony Delroy

Reputation: 106196

You can modify the copy routine to use a template to do the casting...

template <typename A, typename B>                                               
const A& cast(const A&, const B& b)                                             
{                                                                               
    return *reinterpret_cast<const A*>(&b);                                     
};                                                                              

template <class InputIterator, class OutputIterator>                            
OutputIterator mycopy(InputIterator first, InputIterator last,                    
                      OutputIterator result)                                      
{                                                                               
    for ( ; first != last; ++first, ++result)                                   
        *result = cast(*result, *first);                                        
    return result;                                                              
}

That said, Oli's answer's much better if your not specifically looking to learn how to modify copy to handle this....

Upvotes: 1

Oliver Charlesworth
Oliver Charlesworth

Reputation: 272647

Not a precise answer to your question, but it sounds like you want don't really want to std::copy, you want to std::transform your data to another type. In which case, do something like:

template <typename A, typename B>
B convert(A x) { return static_cast<B>(x); }

...

std::transform(v1.begin(), v1.end(), v2.begin(), convert<float,int>);

Upvotes: 1

Armen Tsirunyan
Armen Tsirunyan

Reputation: 133064

yes, the type of *result is ('cause the type of result is OutputIterator )

typename std::iterator_traits<OutputIterator>::value_type

of course, if OutputIterator is a pointer or a correctly written STL-compatible iterator. Otherwise, no, I think there is no way. In the upcoming C++0x, it would be much easier, that is,

decltype(*result)

HTH,

Armen

Upvotes: 6

Related Questions