The real solution here would be to define the appropriate iterator, something like:
class PcmIter : public std::iterator<std::forward_iterator_tag, short> { int myIndex; double myAmplitude; double myFrequency; short myValue; void calculate() { myValue = myAmplitude * std::sin( 2 * M_PI * myIndex * frequency ); } public: PcmIter( int index, amplitude = 0.0, frequency = 0.0 ) : myIndex( index ) , myAmplitude( amplitude ) , myFrequency( frequency ) { calculate(); } bool operator==( PcmIter const& other ) const { return myIndex == other.myIndex; } bool operator!=( PcmIter const& other ) const { return myIndex != other.myIndex; } const short& operator*() const { return myValue; } PcmIter& operator++() { ++ myIndex; calculate(); } PcmIter operator++( int ) { PcmIter results( *this ); operator++(); return results; } };
In practice, I suspect that you could operator* returns the value that you are calculating at this point and does not have a member of myValue .
For use:
std::vector<short> pcmData( PcmIter( 0, amplitude, frequency), PcmIter( buffer_size ) );
(The amplitude and frequency do not matter for the end of the iterator, since it will never be dereferenced.)
Ideally, this would be random_access_iterator, so the constructor for the vector will calculate the number of elements and pre-distribute them. This involves the implementation of a much larger function.
If you are courageous and have to do such things a lot, you might consider creating a template iterator created in accordance with the function you are interested in.
And while I havenβt had a chance to play with them lately, if you use Boost, you can think of a chain of a transform_iterator and a counting_iterator . It's still a little verbal, but the people who did iterators in Boost are the best they could, given the somewhat disrupted design of STL iterators.
James kanze
source share