2010-08-05 9 views
0

Je me demande si et comment il est possible de définir un objet fonction dans une fonction membre classes pour l'utiliser directement avec, par exemple, la fonction std :: transform.
Je sais que l'exemple est un peu stupide, c'est juste pour montrer le problème auquel je suis confronté.Déclaration et définition d'un objet fonction dans une fonction membre de classe

Fichier "example.h"

class Example { 
    public: 
    //.. constructor and destructor stuff 
    std::string toString() const; //Converts 'mVal' to a std::string 

    private: 
    std::vector<int> mVal; //Only one digit numbers are allowed ([0-9]) 
} 

Fichier "example.cpp"

std::string Example::toString() const 
{ 
    //The functor which should be used in std::transform 
    struct { 
    char operator()(const int number) { 
     char c; 
     //"Convert" 'number' to a char 
     return c; 
    }; 
    } functor; 

    //Transform the integers to char 
    std::string str(mVal.size(), '0'); //Allocate enough space 
    std::transform(mVal.begin(), mVal.end(), str.begin(), functor); 
    return str; 

};//toString() 

Depuis que j'ai essayé de mettre en œuvre un objet de fonction directement dans une fonction membre comme dans « example.cpp ", le code n'est pas compilé. Le message d'erreur que je reçois est:

error: no matching function for call to ‘transform(__gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<const int*, std::vector<int, std::allocator<int> > >, __gnu_cxx::__normal_iterator<char*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, Example::toString() const::<anonymous struct>&)’ 

Je pense donc que le problème se pose lors de l'utilisation du struct « foncteur » dans std :: transformer. Quelqu'un peut-il me dire quel est le problème? Utilisation de:
compilateur gcc-4.2 sous Ubuntu Linux. Merci d'avance,
René.

+0

Voir http://stackoverflow.com/questions/2662843/c-can-local-class-reference-be-passed-to-a-function –

+0

double possible [Utilisation de classes locales avec des algorithmes STL] (http://stackoverflow.com/questions/742607/using-local-classes-with-stl-algorithms) –

+0

Oui, vous avez raison. Je ne connaissais pas les termes de recherche exacts. – PiJ

Répondre

4

, vous ne pouvez pas utiliser un type avec une portée de fonction (ou pas de nom du tout) en tant que paramètre de modèle. Vous pouvez toutefois utiliser une fonction membre statique d'un type local en tant que paramètre foncteur:

int main() 
{ 
    struct F { 
     static int fn(int x) 
     { 
      return x+x; 
     } 
    }; 

    int v[5]={1,2,3,4,5}; 
    std::transform(v+0,v+5,v+0,F::fn); 
} 

Si vous avez besoin d'un état local dans votre fonction et ne veulent pas avoir recours à l'idiome d'effacement de type, vous pouvez tricher avec la coulée du type local loin:

int main() 
{ 
    struct F { 
     int k; 
     int call (int n) const 
     { 

      return n+k; 
     } 
     static int fn(void *p, int x) 
     { 
      return ((F*)p)->call(x); 
     } 
    }; 

    int v[5]={1,2,3,4,5}; 
    F f; 
    f.k=123; 
    std::transform(v+0,v+5,v+0,std::bind1st(std::ptr_fun(F::fn),(void*)&f)); 
} 
+0

15 lignes pour une expression lambda ... Mais oui, cela résout le problème. –

+0

Le premier exemple fait l'affaire. Merci pour ça :) . – PiJ

2

Malheureusement, cela ne fonctionnera pas. Standard classes locales à interdit utiliser comme arguments de modèle, de sorte que l'approche ne (s'il vous plaît quelqu'un, je cite la partie pertinente de la norme) :

14.3.1/2: « Un type local, un type avec aucun lien, un type sans nom ou un type composé à partir de l'un de ces types ne doit pas être utilisé comme argument de modèle pour un paramètre de type modèle . "

Si vous avez accès à un compilateur C++ 0x cela fonctionne bien.

classes locales auraient pu être puissants, mais leur utilisation est quelque peu limitée au « langage d'effacement de type »: Comme Alexandre a déjà signalé

struct abstract_foo { ... }; 

template <typename T> 
abstract_foo* make_concrete_foo(...) 
{ 
    struct foo : abstract_foo 
    { 
     // Depends on T 
    }; 

    return new foo(...); 
} 
+0

ISO/CEI 14882 - 14.3.1/2: "Un type local, un type sans liaison, un type sans nom ou un type composé à partir de l'un de ces types ne doit pas être utilisé comme * argument-modèle * pour un modèle * type-paramètre *. " –

+0

Malheureusement, je ne peux pas encore utiliser un compilateur C++ 0x. Mais merci pour la réponse de toute façon, bon de savoir que c'est dans la prochaine norme. – PiJ

+0

@ pij82: Regardez la réponse de Luther avant d'abandonner cependant, c'est suffisant pour vos besoins. –

Questions connexes