Je travaille sur un code où je calcule la durée et je l'enregistre dans la liste.
auto itr = dTimeList.begin(); advance(itr, 0); std::chrono::duration<double> t = 0.0; dTimeList.insert(itr, t);
Maintenant, ici, je dois enregistrer time_duration
dans une liste à un index donné. Si cet index donné contient déjà une valeur, je dois ajouter time_duration
avec la valeur actuelle de cet index et l'enregistrer. Pour cela, j'ai la liste et le code ci-dessous:
list <std::chrono::duration<double>> dTimeList; auto iter = dTimeList.begin(); advance(iter, 0); *iter+= time_duration; //Error at this line
Mais en exécutant le code ci-dessus, j'obtiens l'erreur ci-dessous:
Cette erreur survient probablement parce que j'ai une liste vide sans élément. C'est pourquoi j'ai pensé à ajouter un élément au 0ème index comme ci-dessous:
auto start_time = std::chrono::high_resolution_clock::now(); /* *some code here */ auto finish_time = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> time_duration = finish_time - start_time ;
mais encore une fois ci-dessus donne également une erreur ci-dessous. Comment puis-je résoudre ce problème. Merci
Aucun constructeur approprié disponible pour convertir double en std :: chrono :: duration
3 Réponses :
Vous essayez d'écrire jusqu'à l'itérateur de fin. Lorsque la liste est vide, dTimeList.begin () == dTimeList.end ()
, donc vous ne pouvez pas y écrire.
Vous devez d'abord vérifier si l'index existe, et l'étendre sinon la liste:
void add_time_to_list( std::map<std::size_t, std::chrono::duration<double>>& m, const std::chrono::duration<double>& t, std::size_t index = 0 ) { m[index] += t; // if m[index] doesn't exist, it is default constructed. }
Notez que l'accès à des index arbitraires comme celui-ci peut signifier que vous ne voulez pas d'un std :: list
. Ce serait plus facile avec un std :: vector
( * std :: next (l.begin (), index)
devient l [index] code >). Je suggérerais également un
std :: map
, où la fonction peut simplement être écrite comme:
void add_time_to_list( std::list<std::chrono::duration<double>>& l, const std::chrono::duration<double>& t, std::size_t index = 0 ) { if (index < l.size()) { *std::next(l.begin(), index) += t; } else if (index == l.size()) { // New element; add to back l.push_back(t); } else { // Here you can throw an error that index is too big // or append 0 until it gets to the desired size or something } }
Vous ne devriez probablement pas utiliser la liste pour stocker des données à l'index. Essayez d'utiliser std :: unordered_map
à la place.
auto it = dTimes.find(objectId); if (it != dTimes.end()) { *it += time_duration; } else { dTimes.insert(std::make_pair(objectId, time_duration)); }
et maintenant insérez ou mettez à jour un élément comme celui-ci:
dTimes[objectId] += time_duration;
ou comme ceci:
#include <unordered_map> auto start_time = std::chrono::high_resolution_clock::now(); /* *some code here */ auto finish_time = std::chrono::high_resolution_clock::now(); std::chrono::duration<double> time_duration = finish_time - start_time ; typedef int YourObjectIdType; std::unordered_map<YourObjectIdType, std::chrono::duration<double>> dTimes;
aussi, vous pouvez utiliser std :: map
de la même manière, c'est légèrement plus lent, mais [ begin ()
, la plage end ()
) est triée.
Merci pour cet exemple. Pouvez-vous me dire ce que cela signifie typedef int YourObjectIdType;
Comme je le vois dans votre question précédente, vous avez un identifiant d'objet de type inconnu (pour moi), vous pouvez utiliser cet object_id comme clé de type correspondant dans std :: unordered_map
ou dans std: : carte
. typedef
n'est pas nécessaire. Je suppose simplement que ce type est int
.
Soit vous pouvez utiliser l'index int
ou std :: size_t
comme clé pour ces cartes
Vote positif, mais envisagez d'utiliser dTimes.emplace (objectId, time_duration);
au lieu de dTimes.insert (std :: make_pair (...
Je ne vois aucune logique de stockage par index 0,1,2,3 ... N, et de ne pas utiliser de vecteur? Savons-nous quelle est la logique de l'application ici? Il se peut que std :: vector suffise.
Avez-vous compilé et exécuté ce qui précède?
Aucun constructeur approprié disponible pour convertir double en std :: chrono :: duration
J'ose suggérer que le traitement de std :: list est loin d'être un problème majeur ici.
En ce qui concerne
std :: chrono
, il faut en connaître les concepts de base . Pour ce qui n'est pas expliqué ici, veuillez le rechercher sur cppreference.comPremière étape. Vous décidez quelle horloge vous avez besoin / souhaitez utiliser.
// time_durations_sequence_type tdst for (auto duration : tdst ) { std::cout << std::endl << duration.count() << " nano seconds" << std::endl; }Deuxième étape. Vous utilisez le type imbriqué de durée, déclaré dans celui-ci. Dans votre cas d'utilisation, vous aimeriez avoir une séquence de durées.
time_durations_sequence_type tdst{ time_duration } ;la dénomination des types est très importante. J'utilise délibérément le terme générique de «séquence». Vous pourriez pousser l'idée de std :: list pour l'implémenter, mais je ne vois pas pourquoi. J'utilise donc
std :: vector
ci-dessus.Notez également que je n'utilise pas
double
oulong int
comme le type "durée". Premièrement,std :: duration
est un "temps nécessaire pour qu'un événement se produise". Deuxièmement, ce n'est pas un scalaire, c'est un type de classe. Traditionnellement, à partir des années C, le concept de temps était basé uniquement sur les tiques.Donc, pour couper court à l'histoire, nous utilisons le concept std :: duration, concrétisé comme un type imbriqué dans «l'horloge» que nous avons choisi d'utiliser ici.
// two points in time auto start_time = Clock::now(); auto finish_time = Clock::now(); // the duration Clock::duration time_duration = finish_time - start_time ;Et surtout, c'est tout ce dont nous avons besoin pour mettre en œuvre la fonctionnalité dont vous avez besoin.
// not a point in time Clock::duration // // there is no guarantee above // is the same type as // std::chrono::duration<double> // and we do not need oneMaintenant, nous stockons la durée dans notre type de séquence.
using time_durations_sequence_type = std::vector<Clock::duration> ;Et ailleurs, nous utilisons la séquence de durées stockées que nous avons accumulées.
using Clock = typename std::chrono::high_resolution_clock ;Remarquez comment ci-dessus, nous avons utilisé la méthode
count ()
pour obtenir les graduations réelles, qui par std :: chrono default, représentent des nanosecondes.Le code de travail est ici .
L'erreur que vous obtenez lorsque vous essayez d'avancer l'itérateur lorsqu'il se trouve à
end ()
est, comme vous l'avez compris, claire. Cependant, vous ne nous dites jamais ce qui ne va pas avec le deuxième essai. Créez un exemple reproductible minimal .Utilisez
list.push_back (t)
pour ajouter des éléments à la liste, n'utilisez pasadvance (itr, 0)
@TedLyngmo J'ai édité la question.
@ user2807083 Je dois enregistrer à un index particulier dans la liste, je ne peux donc pas utiliser
list.push_back (t)
Il n'y a pas de constructeur approprié disponible pour convertir
double
enstd::chrono
. Cependant vous pouvez utiliser la construction explicite :std :: chrono :: duration t {0.0};
.@SAndrew Une
liste
ne convient pas si vous souhaitez une indexation. (En fait, ils ne conviennent pas à la plupart des choses et sont rarement observés à l'état sauvage.) Utilisezstd :: vector
oustd :: deque
.@molbdnilo Si vous souhaitez enregistrer à un index particulier, vous pouvez utiliser
std :: map
à la place.@ Ville-Valtteri Cela pourrait aussi être une bonne idée, en particulier si la séquence peut avoir des "trous".