1
votes

Comment déclarer une variable std :: chrono :: duration en C ++

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:

 entrez la description de l'image ici a>

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


8 commentaires

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 pas advance (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 en std::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.) Utilisez std :: vector ou std :: 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".


3 Réponses :


1
votes

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
    }
}


0 commentaires

2
votes

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.


6 commentaires

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?



1
votes

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.com

Premiè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 ou long 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 one

Maintenant, 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 .


0 commentaires