[C++] Szablony funkcji

0

Funkcja f przyjmuje jako parametry argument typu vector<vector<pair<,> > > lub vector<list<pair<,> > >. Jak powinien wyglądać szablon funkcji, żeby możliwe było określenie wewnętrznego kontenera danych (czyli czy jest to vector<pair<,> > czy list<pair<,> >)?? Wewnątrz funkcji potrzebny jest iterator to kontenera wewnętrznego. Czy możliwe jest takie stworzenie szablonu, żeby uzyskać informacje o typie tego kontenera, a jeśli nie - to w jaki sposób tworzyć iterator zależny od typy tego kontenera??

Kod wygląda tak:
typedef int EDGE1;
typedef double EDGE2;
typedef int VERTEX1;

typedef pair<VERTEX1,EDGE1> NEIGHBOUR1;
typedef pair<VERTEX1,EDGE2> NEIGHBOUR2;

typedef vector<vector<NEIGHBOUR1> > g1;
typedef vector<list<NEIGHBOUR2> > g2;

int main(void)
g1 x(21);
g2 y(21);
f(x,1,1);
f(y,1,1);

void f([vector<vector<pair<,> > > lub vector<list<pair<,> > >] a, int b, int c) {
}

Na razie potrzebme są dwie definicji funkcji f, jedna dla vector<vector<pair<,> > >, druga dla vector<list<pair<,> > >...

0

Dżizas, uprość ten program, zrób klasy dla tych list i wektorów, bo to masakra jest...

#include <vector>
#include <list>
#include <iostream>
#include <algorithm>
using namespace std;

typedef int EDGE1;
typedef double EDGE2;
typedef int VERTEX1;

typedef pair<VERTEX1,EDGE1> NEIGHBOUR1;
typedef pair<VERTEX1,EDGE2> NEIGHBOUR2;

typedef vector< vector<NEIGHBOUR1> > g1;
typedef vector< list<NEIGHBOUR2> > g2;

template <typename TT>
class DOIT
{
public:
    void operator()(const TT &p)
    {
        cout << "doit()" << endl;
        // TT => vector<> lub list<>
        cout << "DOIT() with " << p.first << '\t' << p.second << endl;
        cout << endl;
    }
};

template <typename GG>
void f(GG a, int b, int c)
{
    typedef typename GG::value_type     inner_type;
    
    cout << "f()" << endl;
    for (size_t i=0; i<a.size(); i++) // vector<
    {
        // vector<> lub list<>
        inner_type x = a[i];
        // kazda pair<> jest przetwarzana
        for_each( x.begin(), x.end(), DOIT<typename inner_type::value_type>() );
    }
}

int main(void)
{
    g1 x(21);
    vector<NEIGHBOUR1> vv1;
    vv1.push_back( make_pair<VERTEX1,EDGE1>(0,1) );
    vv1.push_back( make_pair<VERTEX1,EDGE1>(2,3) );    
    x.push_back( vv1 );
    
    g2 y(21);
    list<NEIGHBOUR2> vv2;
    vv2.push_back( make_pair<VERTEX1,EDGE2>(0,1.67) );
    vv2.push_back( make_pair<VERTEX1,EDGE2>(2,3.789) );    
    y.push_back( vv2 );


    f(x,1,1);
    f(y,1,1);
}

Wyjście:

f()
doit()
DOIT() with 0   1

doit()
DOIT() with 2   3

f()
doit()
DOIT() with 0   1.67

doit()
DOIT() with 2   3.789

Do typu przechowywanego w wektorze dostajesz się przez

vector<>::value_type

, możesz go po swojemu wykorzystać. Iteratory też są zdefiniowane we wzorcu [z libstd++ MinGW]:

    public:
      typedef _Tp                value_type;
      typedef typename _Alloc::pointer                   pointer;
      typedef typename _Alloc::const_pointer             const_pointer;
      typedef typename _Alloc::reference                 reference;
      typedef typename _Alloc::const_reference           const_reference;
      typedef __gnu_cxx::__normal_iterator<pointer, vector_type> iterator;
      typedef __gnu_cxx::__normal_iterator<const_pointer, vector_type>
      const_iterator;
      typedef std::reverse_iterator<const_iterator>  const_reverse_iterator;
      typedef std::reverse_iterator<iterator>       reverse_iterator;
      typedef size_t                size_type;
      typedef ptrdiff_t                difference_type;
      typedef typename _Base::allocator_type       allocator_type;

Zresztą popatrz w kod, zapewne zrozumiesz, bo sam taki hardcore piszesz... :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1