Question

Je me demandais si quelqu'un peut me aider avec foncteurs. Je ne comprends vraiment ce que foncteurs sont et comment ils fonctionnent, je l'ai essayé googler, mais je ne l'obtenir encore. comment fonctionnent les foncteurs et comment fonctionnent-ils avec des modèles

Était-ce utile?

La solution

Un foncteur est essentiellement un « objet de fonction ». Il est une seule fonction que vous avez enveloppé dans une classe ou struct, et que vous pouvez passer à d'autres fonctions.

Ils travaillent en créant votre propre classe ou struct qui surchargent l'opérateur d'appel de fonction (opérateur appelé ()). En règle générale, vous créez une instance de celui-ci par elle simplement la construction en place comme argument à votre fonction qui prend un foncteur.

Supposons que vous avez les éléments suivants:

std::vector<int> counts;

Maintenant, vous voulez augmenter tous les chefs d'accusation contenus dans ce vecteur. Vous pouvez boucle à travers eux manuellement pour incrémenter, ou vous pouvez utiliser un foncteur. Un foncteur approprié, dans ce cas, ressemblerait à ceci:

struct IncrementFunctor
{
    int operator() (int i)
    {
        return i + 1;
    }
}

IncrementFunctor est maintenant un foncteur qui prend un nombre entier quelconque et il incrémente. Pour l'appliquer à des comptes, vous pouvez utiliser le std :: fonction de transformation, qui prend un foncteur comme argument.

std::transform(
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor

Le IncrementFunctor () syntaxe crée une instance de ce foncteur qui est ensuite transmis directement à std :: transformer. Vous pouvez, bien sûr, créer une instance comme une variable locale et le transmettre, mais cela est beaucoup plus pratique.

Maintenant, sur des modèles. Le type de foncteur dans std :: transformation est un argument de modèle. En effet, std :: transformer ne sait pas (ou de soins!) Dont tapez votre foncteur est. Tout ce qu'il se soucie est qu'il a un opérateur approprié () défini, pour lequel il peut faire quelque chose comme

newValue = functor(oldValue);

Le compilateur est assez intelligent sur les modèles, et peut souvent comprendre lui-même ce que les arguments de modèle sont. Dans ce cas, le compilateur réalise automatiquement que vous passez dans un paramètre de type IncrementFunctor, qui est défini comme un type de modèle dans std :: transformer. Il fait la même chose pour la liste, aussi, de sorte que le compilateur reconnaît automatiquement que l'appel devrait ressembler à ceci:

std::transform<std::vector<int>::iterator, // type of the input iterator
               std::vector<int>::iterator, // type of the output iterator
               IncrementFunctor>(          // type of your functor
    counts.begin(),       // the start of the input range
    counts.end(),         // the end of the input range
    counts.begin(),       // the place where transform should place new values. 
                          // in this case, we put it right back into the original list.
    IncrementFunctor());  // an instance of your functor

Il vous permet d'économiser un peu de frappe. ;)

Autres conseils

Un foncteur est quelque chose qui peut être invoqué / appelé le opérateur d'appel de fonction , syntaxiquement en annexant (), avec le cas échéant une liste d'arguments dans les parenthèses.

C'est tout a besoin de modèle. La chose sur laquelle c'est invoqué, dans la mesure où un modèle est concerné, est tout ce qui permet cette syntaxe - ou en d'autres termes, que ce soit une fonction libre ou une instance d'une classe qui l'emporte sur operator()(). (Une fonction « libre » est juste un qui est pas membre, qui est, il est une fonction à portée globale ou d'une fonction à la portée d'un espace de noms précédemment inclus.)

En dehors du modèle métaprogrammation, nous ne disons pas généralement qu'une fonction libre est un foncteur, et ce nom se réserve pour une instance d'une classe qui remplace operator()():

struct Foo {
 public:
   void operator()( int i ) { // do something }
   void operator()( int i, char x ) { // do something else }
}

Dans les modèles de C sont compilés, donc tant que le syntaxe est logique , le compilateur se fera un plaisir d'utiliser une fonction ou un foncteur:

template<typename T> class Bar {
  private int j ;
  public:
    Bar( int i ) : j(i) {}
    void doIt(T t) {
     t( j ) ;
  }
}

Foo f;
extern void resize( int i ) ; // in some header

Bar<Foo> bf( 5 ) ;
// a Bar that is templated on Foo
Bar< void (&)(int)   > br( 5 ) ; 
// a Bar that is templated on a function taking int and returning void

br.doit( &resize ) ; // call resize with br.j
bf.doit( f ) ; // call Foo::operator()(int) on Foo f with bf.j
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top