STL: container és template

 ( Toth Lali | 2008. november 5., szerda - 10:35 )

Van egy vector-om, ami container-eket tartalmaz: pl. vector<set<int>>. Szeretnék egy másik vector-t, amelyik a méreteket tartalmazza (tehát a 0-ik elem a 0-ik set<int> mérete).
Egy lehetőség:

template <class T>
struct Sizer : public unary_function<T,typename T::size_type>
{
  typename T::size_type operator()(const T& x) const
  {
    return x.size();
  }
};

template <class T>
vector<typename T::size_type> SizeVector(const vector<T> &Input)
{
  vector<typename T::size_type> SV;
  transform(Input.begin(), Input.end(), back_inserter(SV), Sizer<T>());
  return SV;
};

Eddig OK. De ha nekem list<set<int>>-em is van akkor újra meg kell írni a rutint ezúttal list-tel.
A kérdésem: megoldható template-tel, hogy ne kelljen minden container típusra megírni a SizeVector rutint?

Hozzászólás megjelenítési lehetőségek

A választott hozzászólás megjelenítési mód a „Beállítás” gombbal rögzíthető.

Mi lenne, ha a SizeVector egyből két iterátort kapna bemenő paraméternek vector helyett?

KisKresz

Szerintem a kimenetet is változtatni akarja...

De ha nem, akkor sem feltétlenül kell az iterátor:

template <template <typename U> class T,typename U>
vector<typename U::size_type> SizeVector(const T<U> &Input)
{
  vector SV; 
  transform(Input.begin(), Input.end(), back_inserter(SV), Sizer<U>());
  return SV;
};

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Azért írtam az iterátorokat, mert érzésem szerint az illene bele az STL filozófiájába.

KisKresz

Ebben igazad van, bár az új szabványban elmennek a könnyen használhatóság irányába. :)

Viszont ha a kimenő változó típusát is szeretnéd autómatikusan változtatni, akkor az iterátor nem lesz jó (kivéve, ha van benne valami typedef erre...).

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Ő tudja, mi kell neki, én azért alaposan elgondolkoznék azon, valóban list-ben akarok-e tárolni valamilyen egészeket. :-)

KisKresz

Pedig ha az eredeti külső konténer list, akkor lehet értelme, pl.: ha rendszeresen törölgetünk elemeket a közepéről és a törlés után frissíteni akarjuk a méreteket is.

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Rögtön 3 verzióm is van, attól függően, hogy hogyan értelmezem a feladatot:
1: tetszőleges konténer<konténer>-ből tetszőleges konténer<egész>-be.
2: tetszőleges konténer<konténer>-ből tetszőleges konténer<size_type>-ba.
3: tetszőleges konténer<konténer>-ből a megfelelő konténer<size_type>-ba.


template <typename V,typename T>
V Size1(const T &Input)
{
  V sv=V();
  transform(Input.begin(), Input.end(), back_inserter(sv), Sizer<typename T::value_type>());
  return sv;
} 

template < template <typename I> class J,template <typename V> class T,typename V>
J<typename V::size_type> Size2(const T<V> &Input)
{
  J<typename V::size_type> sv=J<typename V::size_type>();
  transform(Input.begin(), Input.end(), back_inserter(sv), Sizer<V>());
  return sv;
} 


template <template <typename V> class T, typename V>
T<typename V::size_type> Size3(const T<V> &Input)
{
  T<typename V::size_type> sv=T<typename V::size_type>();
  transform(Input.begin(), Input.end(), back_inserter(sv), Sizer<V>());
  return sv;
} 



int main ()
{
...

  vector<set<int>::size_type> sv1=Size1< vector<set<int>::size_type> >(vec);

  vector<set<int>::size_type> sv2=Size2< vector >(vec);

  vector<set<int>::size_type> sv3=Size3(vec);
...
}

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o

Köszönöm mindenkinek a hozzászólását!

tr3w: erre a template-ben template struktúrára nem gondoltam, de majd kiróbálom. Az eredményt fixen vector-ban gondoltam, függetlenül a bemenő container-től.

KisKresz: nem int-eket, hanem set<int>-eket tennék list-be. Például egy adott helyen tartózkodók ID-jeit. Így időrendben megnézhető, hogy hogyan alakult az aktuális létszám.

"nem int-eket, hanem set<int>-eket tennék list-be. Például egy adott helyen tartózkodók ID-jeit. Így időrendben megnézhető, hogy hogyan alakult az aktuális létszám"

Azt arra írtam, ha a visszatérési érték típusa is változna a bemenő container típusára.

KisKresz

Természetesen nem az input struktúrája döntené el az output-ét, hanem a felhasználás módja. Tehát az output akkor lehetne set<int>, ha nem érdekelne az adatok sorrendje (egy idősor esetén ez nem így van).
Ennyire általános módszerre nem gondoltam, mint tr3w 2. verziója.

Akkor neked tényleg az iterátoros megoldás kell. Esetleg az amit KisKresz-nek válaszban írtam...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee."
-- Ted Ts'o