2009-11-27 14 views
1

J'ai du mal à trouver pourquoi je ne peux pas transformer pour travailler avec un template template.Comment utiliser std :: transformer avec des templates

Voici une version simplifiée de la classe de modèle:

template<typename T> 
class base 
{ 
public : 
    base() : all_() {} 
    ~base() {} 
public: 
    bool add(T t) 
    { 
    typename vector<T>::iterator itr 
     = lower_bound(all_.begin(), all_.end(), t); 
    if (itr == all_.end() || *itr != t) 
     { 
     all_.push_back(t); 
     cout << "ok" << endl; 
     return true; 
     } 
    cout << "failed" << endl; 
    return false; 
    } 
    static bool addTo(base<T> *c, T t) 
    { 
    return c->add(t); 
    } 
private : 
    vector<T> all_; 
}; 

Et c'est là que je suis en train d'utiliser transformer pour capturer toute la sortie bool de la fonction de membre d'ajouter:

main() 
{ 
    base<int> test; 
    vector<bool> results; 
    vector<int> toAdd; 
    toAdd.push_back(10); 
    toAdd.push_back(11); 
    toAdd.push_back(10); 
    transform(toAdd.begin(), toAdd.end(), 
      back_inserter(results), 
      bind1st((bool(*)(base<int>*,int))base<int>::addTo, &test)); 
} 

Le Le but est d'insérer chaque membre du conteneur toAdd en utilisant base :: add ou base :: addTo, et de capturer les résultats bool dans les résultats vectoriels

+2

Quelle est la question? Si c'est "pourquoi ce code ne compile pas", alors entre autres choses les définitions de fonctions en C++ doivent avoir un type de retour, et 'main' a le type de retour' int' ;-) –

+0

Pouvez-vous expliquer ce que vous essayez d'atteindre dans transformer? – Naveen

+0

Correct - impossible de compiler. Donner la main au type complet n'est pas une condition préalable à tout compilateur que j'ai utilisé. – youngthing

Répondre

6

Essayez:

transform(toAdd.begin(), toAdd.end(), 
     back_inserter(results), 
     bind1st(mem_fun(&base<int>::add), &test)); 

Le problème est pas le modèle, il est que bind1st repose sur un soutien supplémentaire au travail (voir http://www.sgi.com/tech/stl/AdaptableBinaryFunction.html). AFAIK il ne peut jamais fonctionner sur de simples pointeurs de fonction.

boost::bind peut faire plus de choses, si vous voulez apporter que pour cette situation, vous n'avez pas besoin, cependant. mem_fun tourne une fonction membre non statique en une fonction binaire adaptable. addTo n'est donc pas non plus nécessaire, mais si vous avez besoin d'utiliser une fonction membre statique dans une situation similaire, alors il y a ptr_fun.

+0

Cela fonctionne. Merci pour les conseils, surtout celui pédant. – youngthing

+0

Et la * raison * que cela fonctionne est que "bind1st" n'accepte pas les pointeurs de fonction ordinaires. Il nécessite des objets foncteurs. Les fonctions 'mem_fun' et' ptr_fun' transforment les pointeurs de fonction en foncteurs aptes à être utilisés avec les classeurs. –

+0

@RobKennedy: merci, cela fait beaucoup de sens, et quelque chose que je n'ai pas encore trouvé dans le livre de Josutis STL. Je vous donnerais et onebyone un rec si un pourrait! – youngthing

0

Ajouter ce qui suit à votre classe de base:

typedef base<T>* first_argument_type; 
typedef T second_argument_type; 
typedef bool result_type; 

bool operator() (base<T> *c, T t) const { 
    return c->add(t); 
} 

et le changement de transform:

transform(toAdd.begin(), toAdd.end(), 
      back_inserter(results), bind1st(base<int>(), &test)); 
+0

Ce serait bien si ma classe (base) n'allait stocker qu'un conteneur - ça ne me dérangerait pas que l'opérateur() ajoute simplement un élément. Mon code correct a cependant la base responsable de beaucoup plus. – youngthing

+0

Vous n'avez pas besoin de placer ajouter dans la classe 'base' vous pouvez créer une petite structure, disons 'Adder' qui contient le code que j'ai fourni. Remplacez ensuite la base par "Adder". Mais l'adaptateur mem_fun fonctionne aussi;) –