Fonction template avec un vecteur [Résolu]

Polack77 1100 Messages postés mercredi 22 mars 2006Date d'inscription 15 avril 2018 Dernière intervention - 15 avril 2018 à 13:51 - Dernière réponse : cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention
- 16 avril 2018 à 11:41
Bonjour,

J'ai un soucis de syntaxe (encore).
Bon cette fois ce que je veux faire est (me parait) moins exotique.

Je veux faire une fonction template (heee c'est bien comme ça qu'on dit, un template tout cours peut-être ?) qui me permet de trouver un élément dans un vecteur.
Je ne vois pas comment m'expliquer de façon claire sans exemple alors voila le principe :
- J'ai une classe "point" qui possède comme membre une position en x et y et une fonction "distance from" prenant comme paramètre un autre point et retournant la distance entre les deux points.
- J'ai une classe "véhicule" qui hérite de point (avec vitesse, capacité de transport, quantité déjà chargé, ...).
- J'ai une classe "zone" qui hérite aussi de point (...).

Je voudrais ajouter à tout ça une fonction "donne moi le plus proche" à qui je passe un vecteur de point, de véhicule, ou de zone, sous forme d'objet, de référence, ou de pointeur et qui me retourne un itérateur sur l'élément du vecteur avec la plus petite distance.

Un peut de code (bon je ne m’embête pas trop, tout en public ici, mon "vrais" code est plus propre :p) :
#include <vector>
#include <math.h>

class cl_Point
{
public:
 int m_x;
 int m_y;
 cl_Point() : m_x(0),
  m_y(0)
 {
 }
 long double calculDistance(const cl_Point* AutrePoint) const
 {
  return hypot((long double)(this->m_x - AutrePoint->m_x), (long double)(this->m_y - AutrePoint->m_y));
 }
 //Si possible je voudrais cette fonction en template ici (un vecteur contenant un objet, une référence, ou un pointeur sur une classe héritant de cl_Point)
 // Retourne it end si aucun point dans le vecteur
 std::vector<const cl_Point*>::const_iterator calculTrouveLePlusProche(const std::vector<const cl_Point*> vAutre) const
 {
  long double DistanceMin = -1;
  std::vector<const cl_Point*>::const_iterator ValRetour = vAutre.end();
  for (std::vector<const cl_Point*>::const_iterator itvAutre = vAutre.begin(); itvAutre != vAutre.end(); itvAutre++)
  {
   if (this->calculDistance(*itvAutre) < DistanceMin)
   {
    ValRetour = itvAutre;
   }
  }
  return ValRetour;
 }
/*
template<class T> std::vector<T>::const_iterator calculTrouveLePlusProche(const std::vector<T> vAutre)
{
 long double DistanceMin = -1;
 std::vector<T>::const_iterator ValRetour = vAutre.end();
 for (std::vector<T>::const_iterator itvAutre = vAutre.begin(); itvAutre != vAutre.end(); itvAutre++)
 {
  if (this->calculDistance(*itvAutre) < DistanceMin)
  {
   ValRetour = itvAutre;
  }
 }
 return ValRetour;
}
*/
};
class cl_Vehicule : public cl_Point
{
public:
 int m_vitesse;
 int m_capacite;
 //...
 cl_Vehicule() : cl_Point(), m_vitesse(-1), m_capacite(-1)
 {
 }
};
class cl_Zone : public cl_Point
{
public:
 //...
 cl_Zone() : cl_Point()
 {
 }
};

int main()
{
 cl_Vehicule unVehiculePourLExemple;
 std::vector<cl_Vehicule> vVehicules;
 std::vector<cl_Zone> vZones;
 std::vector<const cl_Vehicule*> vpVehicules;
 std::vector<const cl_Zone*> vpZones;

 vVehicules.push_back(cl_Vehicule());
 vVehicules.push_back(cl_Vehicule());
 vVehicules.push_back(cl_Vehicule());
 vVehicules.push_back(cl_Vehicule());
 vZones.push_back(cl_Zone());
 vZones.push_back(cl_Zone());
 vZones.push_back(cl_Zone());
 for (std::vector<cl_Vehicule>::const_iterator it_vVehicules = vVehicules.begin(); it_vVehicules != vVehicules.end(); it_vVehicules++)
 {
  //Pendant qu'on y est, il n'existerait pas une syntaxe plus porpre ?
  vpVehicules.push_back(&(*it_vVehicules));
 }
 for (std::vector<cl_Zone>::const_iterator it_vZones = vZones.begin(); it_vZones != vZones.end(); it_vZones++)
 {
  vpZones.push_back(&(*it_vZones));
 }
 //Je voudrais maintenant chercher qu'elle est le véhicule le plus proche et le point le plus proche
 // de unVehiculePourLExemple en utilisant indiférament vVehicules, vZones, vpVehicules, ou vpZones


 unVehiculePourLExemple.calculTrouveLePlusProche(vVehicules);
 unVehiculePourLExemple.calculTrouveLePlusProche(vpVehicules);
 unVehiculePourLExemple.calculTrouveLePlusProche(vZones);
 unVehiculePourLExemple.calculTrouveLePlusProche(vpZones);

 return 0;
}


Merci d'avance :)
Afficher la suite 

Votre réponse

1 réponse

cptpingu 3794 Messages postés dimanche 12 décembre 2004Date d'inscriptionModérateurStatut 10 juin 2018 Dernière intervention - Modifié par cptpingu le 16/04/2018 à 19:39
0
Merci
Bonjour.

Quelques petites détails techniques:
- Fais du ++it et pas du it++ (meilleur perf, it++ fais une copie pour rien)
- Si tu es en C++11 (je suppose que oui, tous les compilateurs le gèrent maintenant), alors utilisent auto, ce qui simplifie énormément l'écriture d'itérateurs.
- Idem avec la boucle for étendue, qui te permet souvent de ne pas utiliser d'itérateurs.
- On peut initialiser un vecteur en lui donnant sa taille (et il créera N éléments automatiquement).


Pour en revenir au sujet, il est possible de convertir un type "Fille" en "Maman", mais pas un type "vector<Fille>" en type "vector<Maman>". Ce n'est pas la même chose. Donc, en dehors des template, ce n'est pas possible ce que tu demandes. En revanche il est possible de faire un template, si tu acceptes de changer aussi le type de retour. Vu que tu récupères un itérateur, tu peux aller ensuite chercher la valeur, et le convertir en type "Maman", si tu en as besoin (ça fera ce que tu veux).
Si tu préfères, tu as le droit de faire ça:
iterator sur un vector<*vehicule> => récupérer *vehicule => convertir en *point
mais tu n'as pas le droit de faire ça:
iterator sur un vector<*vehicule> => iterator sur un vector<*point> (impossible, incompatible).

En code, ça donnerait ça:
#include <iostream>
#include <vector>
#include <cmath>

class cl_Point
{
public:
  int m_x;
  int m_y;
  cl_Point() : m_x(0),
               m_y(0)
  {
  }

  long double calculDistance(const cl_Point* AutrePoint) const
  {
    return hypot((long double)(m_x - AutrePoint->m_x), (long double)(m_y - AutrePoint->m_y));
  }
  long double calculDistance(const cl_Point& AutrePoint) const
  {
    return hypot((long double)(m_x - AutrePoint.m_x), (long double)(m_y - AutrePoint.m_y));
  }

  template <typename T>
  typename T::const_iterator calculTrouveLePlusProche(const T& vAutre) const
  {
    static const long double DistanceMin = 1000000;
    auto end = vAutre.end();
    for (auto itvAutre = vAutre.begin(); itvAutre != end; ++itvAutre)
      if (calculDistance(*itvAutre) < DistanceMin)
        return itvAutre;

    return end;
  }
};

class cl_Vehicule : public cl_Point
{
public:
  int m_vitesse;
  int m_capacite;
  //...
  cl_Vehicule() : cl_Point(), m_vitesse(-1), m_capacite(-1)
  {
  }
};
class cl_Zone : public cl_Point
{
public:
  //...
  cl_Zone() : cl_Point()
  {
  }
};

int main()
{
  cl_Vehicule unVehiculePourLExemple;
  std::vector<cl_Vehicule> vVehicules(4);
  std::vector<cl_Zone> vZones(3);
  std::vector<const cl_Vehicule*> vpVehicules;
  std::vector<const cl_Zone*> vpZones;

  for (auto& vehicule : vVehicules)
    vpVehicules.push_back(&vehicule);

  for (auto& zone : vZones)
    vpZones.push_back(&zone);

  {
    auto it = unVehiculePourLExemple.calculTrouveLePlusProche(vVehicules);
    // check it != end
    std::cout << "Ex1: " << it->m_vitesse << " " << it->m_capacite << " " << it->m_x << " " << it->m_y << std::endl;
  }
  {
    auto it = unVehiculePourLExemple.calculTrouveLePlusProche(vpVehicules);
    std::cout << "Ex2: " << (*it)->m_vitesse << " " << (*it)->m_capacite << " " << (*it)->m_x << " " << (*it)->m_y << std::endl;
  }
  {
    auto it = unVehiculePourLExemple.calculTrouveLePlusProche(vZones);
    std::cout << "Ex3: " <<  it->m_x << " " << it->m_y << std::endl;
  }
  {
    auto it = unVehiculePourLExemple.calculTrouveLePlusProche(vpZones);
    std::cout << "Ex4: " << (*it)->m_x << " " << (*it)->m_y << std::endl;
  }

  return 0;
}


Si ça ne convient toujours pas et que tu veux vraiment avoir l'élément, alors tu devras modifier la fonction template pour qu'elle retourne un index au lieu d'un itérateur.


Améliorer votre expérience CodeS-SourceS avec ce plugin:
http://codes-sources.commentcamarche.net/forum/affich-10000111-plugin-better-cs-2#cptpingu-signature
Commenter la réponse de cptpingu

Vous n'êtes pas encore membre ?

inscrivez-vous, c'est gratuit et ça prend moins d'une minute !

Les membres obtiennent plus de réponses que les utilisateurs anonymes.

Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.

Le fait d'être membre vous permet d'avoir des options supplémentaires.