Mon problème est plus complexe que cela. J'ai donc réduit mon problème à un exemple très simple qui me montrerait assez pour savoir comment gérer le reste.Transformation de plusieurs éléments de l'itérateur
Dites que j'ai un itérateur d'entrée. Je veux en faire un nouvel itérateur d'entrée, où chaque élément est la combinaison de plusieurs éléments séquentiels de l'entrée originale avec le motif suivant. La longueur d'exécution est codée dans la séquence d'entrée.
entrée: { 1 1 2 3 4 4 6 7 8 9 ... }
sortie: { (1) (3+4) (6+7+8+9) ... }
Je pensais une fonction de ce type peut traiter un élément unique et incrémenter l'entrée commencent itérateur (transmis par référence). Il y a quelques questions dans mes commentaires, plus j'aimerais savoir s'il y a un bon moyen de le faire pour l'ensemble du flux d'éléments.
EDIT: Je suis conscient qu'il ya un bug dans l'appel à std::advance
où le tmp
iterator est incrémenté d'être end
exactement, ce qui serait valable pour ce code. Concentrons-nous sur le reste de mes questions et je réglerai cela. Modifier 2: devrait être réparé maintenant?
template<class TInputIterator, class TOutputIterator>
void process_single(TInputIterator& begin, TInputIterator end, TOutputIterator destination)
{
std::iterator_traits<TInputIterator>::value_type run_length = *begin;
++begin;
// is there a better way to specify run_length elements to accumulate() without having to call advance() here?
TInputIterator tmp(begin);
std::advance(tmp, run_length);
// Edited: this condition should work for the different kinds of iterators?
if ((end < tmp) || (std::distance(begin, tmp) != run_length))
throw std::range_error("The input sequence had too few elements.");
// std::plus is the default accumulate function
*destination = std::accumulate(begin, tmp, 0/*, std::plus<TInputIterator::value_type>()*/);
// should I use std::swap(begin, tmp) here instead?
begin = tmp;
}
Edit 3: En réponse aux réponses, serait-ce mieux?
template<class TInputIterator, class TOutputIterator>
TInputIterator process_single(TInputIterator begin, TInputIterator end, TOutputIterator destination)
{
typedef std::iterator_traits<TInputIterator>::value_type value_type;
value_type run_length = *begin;
++begin;
value_type sum = 0;
while (run_length > 0 && begin != end)
{
sum += *begin;
++begin;
--run_length;
}
if (run_length)
{
throw std::range_error("The input sequence had too few elements.");
}
*destination = sum;
return begin;
}
template<class TInputIterator, class TOutputIterator>
void process(TInputIterator begin, TInputIterator end, TOutputIterator destination)
{
while (begin != end)
{
begin = process_single(begin, end, destination);
}
}
Je suis honnêtement un peu confus ce que la question est ici .. –