2010-04-26 4 views
1

J'ai écrit une fonction modèle pour déterminer la médiane de tout vecteur ou tableau de tout type pouvant être trié avec tri. La fonction et un petit programme de test sont ci-dessous:Utilisation d'un paramètre de type et d'un pointeur sur le même paramètre de type dans un modèle de fonction

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

template <class T, class X> 
void median(T vec, size_t size, X& ret) 
{ 
    sort(vec, vec + size); 
    size_t mid = size/2; 
    ret = size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid]; 
} 

int main() 
{ 
    vector<double> v; 
    v.push_back(2); v.push_back(8); 
    v.push_back(7); v.push_back(4); 
    v.push_back(9); 

    double a[5] = {2, 8, 7, 4, 9}; 

    double r; 
    median(v.begin(), v.size(), r); 
    cout << r << endl; 
    median(a, 5, r); 
    cout << r << endl; 
    return 0; 
} 

Comme vous pouvez le voir, la fonction médiane prend un pointeur comme argument, T VEC. Également dans la liste d'arguments est une variable de référence X ret, qui est modifiée par la fonction pour stocker la valeur médiane calculée.

Cependant, je ne trouve pas cela une solution très élégante. T vec sera toujours un pointeur vers le même type que X ret. Mes premières tentatives d'écrire médiane avait un en-tête comme ceci:

template<class T> 
T median(T *vec, size_t size) 
{ 
     sort(vec, vec + size); 
     size_t mid = size/2; 
     return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid]; 
} 

J'ai aussi essayé:

template<class T, class X> 
X median(T vec, size_t size) 
{ 
     sort(vec, vec + size); 
     size_t mid = size/2; 
     return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid]; 
} 

Je ne pouvais pas non plus de ces derniers à travailler. Ma question est, quelqu'un peut-il me montrer une mise en œuvre de travail de l'une de mes alternatives?

Merci de votre visite!

+1

Cela ne vous aidera pas, mais vous devez vous assurer que vos clients savent que votre fonction médiane triera leur conteneur en tant qu'effet secondaire. – zneak

+1

Note de côté: 'using namespace :: std;' est bizarre, et ne signifie probablement pas tout à fait ce que vous pensez qu'il fait. Ajuster les espaces le rend plus clair: 'using namespace :: std; ' mais il est beaucoup plus commun d'écrire simplement 'using namespace std;' –

+0

@zneak - Je viens de me rendre compte que je ne * veux pas * le conteneur d'origine trié =/Donc devrais-je travailler avec une copie dans ma fonction? – Darel

Répondre

3

L'approche idiomatique consiste à utiliser des itérateurs. Pour ce faire, vous pouvez déduire le type de retour de la iterator:

template <class I> 
typename iterator_traits<I>::value_type median(I start, I finish) 
{ 
    ... 
} 
0

Je ferais ceci:

template <class T> 
void median(T* vec, size_t size, T& ret) 
{ 
    sort(vec, vec + size); 
    size_t mid = size/2; 
    ret = size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid]; 
} 

template <class T> 
void median(vector<T>& vec, T& ret) 
{ 
     median(&*vec.begin(), vec.size(), ret); 
} 

Mais ce qui est juste moi.

Questions connexes