O que são funcionalidades C++ e suas utilizações?

continuo a ouvir muito sobre functores em C++. Alguém pode dar-me uma visão geral do que são e em que casos seriam úteis?

15 answers

Um functor é praticamente apenas uma classe que define o operador(). Isso permite-lhe criar objectos que "se parecem" com uma função:

// this is a functor
struct add_x {
  add_x(int x) : x(x) {}
  int operator()(int y) const { return x + y; }

private:
  int x;
};

// Now you can use it like this:
add_x add42(42); // create an instance of the functor class
int i = add42(8); // and "call" it
assert(i == 50); // and it added 42 to its argument

std::vector<int> in; // assume this contains a bunch of values)
std::vector<int> out(in.size());
// Pass a functor to std::transform, which calls the functor on every element 
// in the input sequence, and stores the result to the output sequence
std::transform(in.begin(), in.end(), out.begin(), add_x(1)); 
assert(out[i] == in[i] + 1); // for all i
Há algumas coisas boas sobre functores. Uma delas é que, ao contrário das funções regulares, elas podem conter o estado. O exemplo acima cria uma função que adiciona 42 a tudo o que você dá. Mas esse valor 42 não é hardcoded, foi especificado como um argumento construtor quando criamos nossa instância functor. Eu poderia criar outro adder, que acrescentou 27, apenas chamando o construtor com um valor diferente. Isto torna-os facilmente personalizáveis.

Como mostram as últimas linhas, você frequentemente passa functores como argumentos para outras funções como std::transformar ou os outros algoritmos de biblioteca padrão. Você poderia fazer o mesmo com um regular ponteiro de função, exceto, como eu disse acima, o ficheiro pode ser "personalizado", porque eles contêm estado, tornando-as mais flexíveis (Se eu quisesse usar um ponteiro de função, eu teria de escrever uma função que adicionei exactamente 1 ao seu argumento. O functor é geral, e adiciona o que você inicializou com), e eles também são potencialmente mais eficientes. No exemplo acima, o compilador sabe exatamente qual função std::transform deve chamar. Deve ligar. Isso significa que pode inline essa chamada de função. E isso o torna tão eficiente quanto se eu tivesse chamado manualmente a função em cada valor do vetor.

Se eu tivesse passado um ponteiro de função em vez disso, o compilador não poderia ver imediatamente para que Função aponta, então a menos que realize algumas otimizações globais bastante complexas, teria que dereferenciar o ponteiro em tempo de execução, e então fazer a chamada.

 881
Author: jalf, 2015-08-19 18:00:54

Pouca adição. Você pode usar boost::function, para criar funcionalidades a partir de funções e métodos, como este:

class Foo
{
public:
    void operator () (int i) { printf("Foo %d", i); }
};
void Bar(int i) { printf("Bar %d", i); }
Foo foo;
boost::function<void (int)> f(foo);//wrap functor
f(1);//prints "Foo 1"
boost::function<void (int)> b(&Bar);//wrap normal function
b(1);//prints "Bar 1"

E você pode usar o boost:: bind para adicionar estado a este functor {[[9]}

boost::function<void ()> f1 = boost::bind(foo, 2);
f1();//no more argument, function argument stored in f1
//and this print "Foo 2" (:
//and normal function
boost::function<void ()> b1 = boost::bind(&Bar, 2);
b1();// print "Bar 2"

E mais útil, com impulso::: bind and boost:: function you can create functor from class method, actually this is a delegate:

class SomeClass
{
    std::string state_;
public:
    SomeClass(const char* s) : state_(s) {}

    void method( std::string param )
    {
        std::cout << state_ << param << std::endl;
    }
};
SomeClass *inst = new SomeClass("Hi, i am ");
boost::function< void (std::string) > callback;
callback = boost::bind(&SomeClass::method, inst, _1);//create delegate
//_1 is a placeholder it holds plase for parameter
callback("useless");//prints "Hi, i am useless"

Pode criar uma lista ou um vector de funcionalidades

std::list< boost::function<void (EventArg e)> > events;
//add some events
....
//call them
std::for_each(
        events.begin(), events.end(), 
        boost::bind( boost::apply<void>(), _1, e));
Há um problema com tudo isto, as mensagens de erro do compilador não são humanas. legível:)
 113
Author: Lazin, 2017-06-07 11:33:44

Um Functor é um objecto que age como uma função. Basicamente, uma classe que define operator().

class MyFunctor
{
   public:
     int operator()(int x) { return x * 2;}
}

MyFunctor doubler;
int x = doubler(5);

A verdadeira vantagem é que um functor pode manter o estado.

class Matcher
{
   int target;
   public:
     Matcher(int m) : target(m) {}
     bool operator()(int x) { return x == target;}
}

Matcher Is5(5);

if (Is5(n))    // same as if (n == 5)
{ ....}
 76
Author: James Curran, 2017-06-07 11:34:28

O nome "functor" tem sido tradicionalmente usado em Teoria das categorias muito antes do c++ aparecer na cena. Isto não tem nada a ver com o conceito C++ do functor. É melhor usar o nome objecto de função em vez do que chamamos de "functor" em C++. É assim que outras linguagens de programação chamam construções similares.

Usado em vez de função simples:

Características:

  • o objecto da função pode ter estado
  • o objecto da função encaixa-se no OP (comporta-se como qualquer outro objeto).

Conts:

  • traz mais complexidade ao programa.

Usado em vez do ponteiro da função:

Características:

  • o objecto da função muitas vezes pode estar alinhado

Conts:

  • o objecto de função não pode ser trocado por outro tipo de objecto de função durante o período de execução (pelo menos a menos que se estenda alguma classe de base, o que, por conseguinte, dá alguma sobrecarga) {[[13]}

Utilizado em vez de função virtual:

Características:

  • O objecto da função (não-virtual) não necessita de um dispatching vtable e em tempo de execução, pelo que é mais eficiente na maioria dos casos

Conts:

  • o objecto de função não pode ser trocado por outro tipo de objecto de função durante o período de execução (pelo menos a menos que se estenda alguma classe de base, o que, por conseguinte, dá alguma sobrecarga) {[[13]}
 38
Author: doc, 2017-02-13 10:46:57

Como outros já mencionaram, um functor é um objeto que age como uma função, ou seja, sobrecarrega o operador de chamada de função.

Functores são comumente usados em algoritmos STL. Eles são úteis porque eles podem manter o estado antes e entre chamadas de funções, como um fechamento em linguagens funcionais. Por exemplo, você pode definir um functor MultiplyBy que multiplica o seu argumento por um montante especificado:

class MultiplyBy {
private:
    int factor;

public:
    MultiplyBy(int x) : factor(x) {
    }

    int operator () (int other) const {
        return factor * other;
    }
};
Então você poderia passar um objeto MultiplyBy para um algoritmo como Std:: transformar:
int array[5] = {1, 2, 3, 4, 5};
std::transform(array, array + 5, array, MultiplyBy(3));
// Now, array is {3, 6, 9, 12, 15}

Outra vantagem de um functor sobre um ponteiro para uma função é que a chamada pode ser alinhada em mais casos. Se você passou um ponteiro de função para transform, a menos que a chamada foi incorporada e o compilador sabe que você sempre passa a mesma função para ele, ele não pode inline a chamada através do ponteiro.

 34
Author: Matthew Crumley, 2015-09-08 12:03:00
Para os novatos como eu entre nós, depois de uma pesquisa descobri o que o código que o jalf postou fez.

Um functor é um objeto de classe ou estrutura que pode ser chamado como uma função. Isto é possível sobrecarregando o () operator. O () operator (não sei o que é chamado) pode levar qualquer número de argumentos. Outros operadores só tomam dois, ou seja, o + operator só pode tomar dois valores (um de cada lado do operador) e devolver qualquer valor que tenha sobrecarregado. Você pode caber qualquer número de argumentos dentro de um () operator que é o que lhe dá a sua flexibilidade.

Para criar um functor primeiro cria-se a classe. Então você cria um construtor para a classe com um parâmetro de sua escolha de tipo e nome. Isto é seguido na mesma declaração por uma lista de inicialização (que usa um único operador de dois pontos, algo que eu também era novo) que constrói os objetos membros da classe com o parâmetro anteriormente declarado para o construtor. Então o {[1] } está sobrecarregado. Finalmente tu. declare os objetos privados da classe ou estrutura que criou.

O meu código (achei os nomes das variáveis do jalf confusos)

class myFunctor
{ 
    public:
        /* myFunctor is the constructor. parameterVar is the parameter passed to
           the constructor. : is the initializer list operator. myObject is the
           private member object of the myFunctor class. parameterVar is passed
           to the () operator which takes it and adds it to myObject in the
           overloaded () operator function. */
        myFunctor (int parameterVar) : myObject( parameterVar ) {}

        /* the "operator" word is a keyword which indicates this function is an 
           overloaded operator function. The () following this just tells the
           compiler that () is the operator being overloaded. Following that is
           the parameter for the overloaded operator. This parameter is actually
           the argument "parameterVar" passed by the constructor we just wrote.
           The last part of this statement is the overloaded operators body
           which adds the parameter passed to the member object. */
        int operator() (int myArgument) { return myObject + myArgument; }

    private: 
        int myObject; //Our private member object.
}; 
Se isto for incorrecto ou simplesmente errado, corrija-me à vontade!
 28
Author: Johanne Irish, 2015-09-22 21:26:14

Um functor é uma função de ordem superior que aplica uma função aos tipos parametrizados(IE templated). É uma generalização da função map de ordem superior. Por exemplo, poderíamos definir um functor para std::vector Assim:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::vector<U> fmap(F f, const std::vector<T>& vec)
{
    std::vector<U> result;
    std::transform(vec.begin(), vec.end(), std::back_inserter(result), f);
    return result;
}

Esta função toma um std::vector<T> e devolve std::vector<U> quando é dada uma função F que toma um T e devolve um U. Um functor não tem que ser definido sobre tipos de contêiner, ele pode ser definido para qualquer tipo templated como bem, incluindo std::shared_ptr:

template<class F, class T, class U=decltype(std::declval<F>()(std::declval<T>()))>
std::shared_ptr<U> fmap(F f, const std::shared_ptr<T>& p)
{
    if (p == nullptr) return nullptr;
    else return std::shared_ptr<U>(new U(f(*p)));
}
Eis um exemplo simples que converte o tipo a um double:
double to_double(int x)
{
    return x;
}

std::shared_ptr<int> i(new int(3));
std::shared_ptr<double> d = fmap(to_double, i);

std::vector<int> is = { 1, 2, 3 };
std::vector<double> ds = fmap(to_double, is);
Há duas leis que os funcionários devem seguir. A primeira é a lei de identidade, que afirma que se ao functor é dada uma função de identidade, deve ser o mesmo que aplicar a função de identidade ao tipo, ou seja fmap(identity, x) deve ser o mesmo que identity(x):
struct identity_f
{
    template<class T>
    T operator()(T x) const
    {
        return x;
    }
};
identity_f identity = {};

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<int> is1 = fmap(identity, is);
std::vector<int> is2 = identity(is);
([18]) a lei seguinte é a lei da composição, que afirma que se ao functor for dada uma composição de duas funções, deve ser o mesmo que aplicar o functor para a primeira função e, em seguida, novamente para a segunda função. Então, fmap(std::bind(f, std::bind(g, _1)), x) deve ser o mesmo que fmap(f, fmap(g, x)):
double to_double(int x)
{
    return x;
}

struct foo
{
    double x;
};

foo to_foo(double x)
{
    foo r;
    r.x = x;
    return r;
}

std::vector<int> is = { 1, 2, 3 };
// These two statements should be equivalent.
// is1 should equal is2
std::vector<foo> is1 = fmap(std::bind(to_foo, std::bind(to_double, _1)), is);
std::vector<foo> is2 = fmap(to_foo, fmap(to_double, is));
 17
Author: Paul Fultz II, 2017-02-12 17:12:35
Eis uma situação em que fui forçado a usar um Functor para resolver o meu problema.

Eu tenho um conjunto de funções (digamos, 20 delas), e todas elas são idênticas, exceto cada uma chama uma função específica diferente em 3 pontos específicos.

Isto é um desperdício incrível e duplicação de código. Normalmente eu apenas passaria em um ponteiro de função, e apenas chamar isso nos 3 pontos. (Então o código só precisa aparecer uma vez, em vez de vinte vezes.) Mas depois apercebi-me, em em cada caso, a função específica requeria um perfil de parâmetros completamente diferente! Às vezes 2 parâmetros, às vezes 5 parâmetros, etc.

Outra solução seria ter uma classe base, onde a função específica é um método sobreposto numa classe derivada. Mas eu realmente quero construir toda essa herança, só para que eu possa passar um ponteiro de função????

Solução: então o que eu fiz foi, eu fiz uma classe de papel (um "Functor") que é capaz de chamar qualquer uma das funções que eu precisava conhecer. Configuro-o com antecedência (com os seus parâmetros, etc) e depois passo-o em vez de um ponteiro de função. Agora o código chamado pode ativar o Functor, sem saber o que está acontecendo no interior. Ele pode até chamá-lo várias vezes (eu precisava para chamar 3 vezes.)


É isso -- um exemplo prático onde um Functor acabou sendo a solução óbvia e fácil, o que me permitiu reduzir a duplicação de código de 20 funções para 1.
 8
Author: Fellow Traveler, 2011-12-26 06:54:56

Excepto no que se refere ao callback, os functores de C++ também podem ajudar a fornecer uma classe Matlab a gostar do estilo de acesso a uma classe matrix. Há um exemplo.

 2
Author: Shawn Xie, 2012-03-07 07:03:17

Os functores são usados no gtkmm para ligar algum botão GUI a uma função ou método de c++.


Se você usar a biblioteca de pthread para fazer o seu aplicativo multithreaded, os Functors podem ajudá-lo.
Para iniciar um tópico, um dos argumentos do pthread_create(..) é o ponteiro da função a ser executado no seu próprio tópico.
Mas há um inconveniente. Este ponteiro não pode ser um ponteiro para um método, a menos que seja um método estático, ou a menos que você indique que é Classe , tipo class::method E outra coisa, a interface do seu método só pode ser:

void* method(void* something)

Então você não pode executar (de uma forma simples óbvia), métodos de sua classe em um fio sem fazer algo extra.

Uma forma muito boa de lidar com tópicos em C++, é criar a sua própria classe Thread. Se você queria executar métodos da classe MyClass, o que eu fiz foi, transformar esses métodos em classes derivadas Functor.

Também, a classe Thread tem este método.: static void* startThread(void* arg)
Um ponteiro para este método será usado como argumento para chamar pthread_create(..). E o que startThread(..) deve receber em arg é uma referência castada a uma instância em heap de qualquer classe derivada Functor, que será voltada para Functor* quando executada, e então Chamada de método run().

 1
Author: erandros, 2011-10-24 18:57:24
Para acrescentar, usei objectos de função para encaixar um método antigo existente no padrão de comandos (o único lugar onde a beleza do paradigma OO verdadeiro OCP senti ); Também adicionando aqui o padrão de adaptador de funções relacionadas.

Suponha que o seu método tem a assinatura:

int CTask::ThreeParameterTask(int par1, int par2, int par3)

Vamos ver como podemos encaixá - lo para o padrão de comando-para isso, primeiro, você tem que escrever um adaptador de função membro para que ele possa ser chamado como um objeto de função.

Nota: Isto é feio, e ... pode ser que você possa usar os ajudantes Boost bind etc. mas se não podes ou não queres, esta é uma maneira.
// a template class for converting a member function of the type int        function(int,int,int)
//to be called as a function object
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
class mem_fun3_t
{
  public:
explicit mem_fun3_t(_Ret (_Class::*_Pm)(_arg1,_arg2,_arg3))
    :m_Ptr(_Pm) //okay here we store the member function pointer for later use
    {}

//this operator call comes from the bind method
_Ret operator()(_Class *_P, _arg1 arg1, _arg2 arg2, _arg3 arg3) const
{
    return ((_P->*m_Ptr)(arg1,arg2,arg3));
}
private:
_Ret (_Class::*m_Ptr)(_arg1,_arg2,_arg3);// method pointer signature
};
Além disso, precisamos de um método auxiliar mem_fun3 para a classe acima ajudar na chamada.
template<typename _Ret,typename _Class,typename _arg1,typename _arg2,typename _arg3>
mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3> mem_fun3 ( _Ret (_Class::*_Pm)          (_arg1,_arg2,_arg3) )
{
  return (mem_fun3_t<_Ret,_Class,_arg1,_arg2,_arg3>(_Pm));

}

Agora, para ligar os parâmetros, temos de escrever uma função binder. Então, aqui vai:
template<typename _Func,typename _Ptr,typename _arg1,typename _arg2,typename _arg3>
class binder3
{
public:
//This is the constructor that does the binding part
binder3(_Func fn,_Ptr ptr,_arg1 i,_arg2 j,_arg3 k)
    :m_ptr(ptr),m_fn(fn),m1(i),m2(j),m3(k){}

 //and this is the function object 
 void operator()() const
 {
        m_fn(m_ptr,m1,m2,m3);//that calls the operator
    }
private:
    _Ptr m_ptr;
    _Func m_fn;
    _arg1 m1; _arg2 m2; _arg3 m3;
};

E, uma função auxiliar para usar a classe binder3:

//a helper function to call binder3
template <typename _Func, typename _P1,typename _arg1,typename _arg2,typename _arg3>
binder3<_Func, _P1, _arg1, _arg2, _arg3> bind3(_Func func, _P1 p1,_arg1 i,_arg2 j,_arg3 k)
{
    return binder3<_Func, _P1, _arg1, _arg2, _arg3> (func, p1,i,j,k);
}

Agora, temos que usar isto com a classe de comando; use o seguinte typedef:

typedef binder3<mem_fun3_t<int,T,int,int,int> ,T* ,int,int,int> F3;
//and change the signature of the ctor
//just to illustrate the usage with a method signature taking more than one parameter
explicit Command(T* pObj,F3* p_method,long timeout,const char* key,
long priority = PRIO_NORMAL ):
m_objptr(pObj),m_timeout(timeout),m_key(key),m_value(priority),method1(0),method0(0),
method(0)
{
    method3 = p_method;
}
Eis como se chama:
F3 f3 = PluginThreadPool::bind3( PluginThreadPool::mem_fun3( 
      &CTask::ThreeParameterTask), task1,2122,23 );

Nota: f3 (); chamará ao método task1->ThreeParameterTask (21,22,23);.

O contexto completo deste padrão na seguinte ligação

 1
Author: Alex Punnen, 2013-01-28 06:50:37

Como foi repetido, os functores são classes que podem ser tratadas como funções (operador de sobrecarga).

Eles são mais úteis para situações em que você precisa associar alguns dados com chamadas repetidas ou atrasadas para uma função.

Por exemplo, uma lista ligada de functores poderia ser usada para implementar um sistema básico de coroutina síncrona, um despachante de tarefas ou processamento de arquivos interruptíveis. Exemplos:

/* prints "this is a very simple and poorly used task queue" */
class Functor
{
public:
    std::string output;
    Functor(const std::string& out): output(out){}
    operator()() const
    {
        std::cout << output << " ";
    }
};

int main(int argc, char **argv)
{
    std::list<Functor> taskQueue;
    taskQueue.push_back(Functor("this"));
    taskQueue.push_back(Functor("is a"));
    taskQueue.push_back(Functor("very simple"));
    taskQueue.push_back(Functor("and poorly used"));
    taskQueue.push_back(Functor("task queue"));
    for(std::list<Functor>::iterator it = taskQueue.begin();
        it != taskQueue.end(); ++it)
    {
        *it();
    }
    return 0;
}

/* prints the value stored in "i", then asks you if you want to increment it */
int i;
bool should_increment;
int doSomeWork()
{
    std::cout << "i = " << i << std::endl;
    std::cout << "increment? (enter the number 1 to increment, 0 otherwise" << std::endl;
    std::cin >> should_increment;
    return 2;
}
void doSensitiveWork()
{
     ++i;
     should_increment = false;
}
class BaseCoroutine
{
public:
    BaseCoroutine(int stat): status(stat), waiting(false){}
    void operator()(){ status = perform(); }
    int getStatus() const { return status; }
protected:
    int status;
    bool waiting;
    virtual int perform() = 0;
    bool await_status(BaseCoroutine& other, int stat, int change)
    {
        if(!waiting)
        {
            waiting = true;
        }
        if(other.getStatus() == stat)
        {
            status = change;
            waiting = false;
        }
        return !waiting;
    }
}

class MyCoroutine1: public BaseCoroutine
{
public:
    MyCoroutine1(BaseCoroutine& other): BaseCoroutine(1), partner(other){}
protected:
    BaseCoroutine& partner;
    virtual int perform()
    {
        if(getStatus() == 1)
            return doSomeWork();
        if(getStatus() == 2)
        {
            if(await_status(partner, 1))
                return 1;
            else if(i == 100)
                return 0;
            else
                return 2;
        }
    }
};

class MyCoroutine2: public BaseCoroutine
{
public:
    MyCoroutine2(bool& work_signal): BaseCoroutine(1), ready(work_signal) {}
protected:
    bool& work_signal;
    virtual int perform()
    {
        if(i == 100)
            return 0;
        if(work_signal)
        {
            doSensitiveWork();
            return 2;
        }
        return 1;
    }
};

int main()
{
     std::list<BaseCoroutine* > coroutineList;
     MyCoroutine2 *incrementer = new MyCoroutine2(should_increment);
     MyCoroutine1 *printer = new MyCoroutine1(incrementer);

     while(coroutineList.size())
     {
         for(std::list<BaseCoroutine *>::iterator it = coroutineList.begin();
             it != coroutineList.end(); ++it)
         {
             *it();
             if(*it.getStatus() == 0)
             {
                 coroutineList.erase(it);
             }
         }
     }
     delete printer;
     delete incrementer;
     return 0;
}
É claro que estes exemplos não são assim tão úteis. em si mesmos. Eles só mostram como os functors podem ser úteis, os próprios functors são muito básicos e inflexíveis e isso os torna menos úteis do que, por exemplo, o impulso fornece.
 1
Author: nfries88, 2014-02-08 05:34:56

Uma grande vantagem de implementar funções como functores é que eles podem manter e reutilizar o estado entre as chamadas. Por exemplo, muitos algoritmos de programação dinâmica, como o algoritmo Wagner-Fischer para calcular a distância de Levenshtein entre cadeias, funcionam preenchendo uma grande tabela de resultados. É muito ineficiente alocar esta tabela cada vez que a função é chamada, então implementar a função como um functor e fazer da tabela uma variável Membro pode melhorar muito o desempenho.

Abaixo está um exemplo de implementação do algoritmo Wagner-Fischer como um functor. Observe como a tabela é alocada no construtor, e então reutilizada em operator(), com redimensionamento conforme necessário.

#include <string>
#include <vector>
#include <algorithm>

template <typename T>
T min3(const T& a, const T& b, const T& c)
{
   return std::min(std::min(a, b), c);
}

class levenshtein_distance 
{
    mutable std::vector<std::vector<unsigned int> > matrix_;

public:
    explicit levenshtein_distance(size_t initial_size = 8)
        : matrix_(initial_size, std::vector<unsigned int>(initial_size))
    {
    }

    unsigned int operator()(const std::string& s, const std::string& t) const
    {
        const size_t m = s.size();
        const size_t n = t.size();
        // The distance between a string and the empty string is the string's length
        if (m == 0) {
            return n;
        }
        if (n == 0) {
            return m;
        }
        // Size the matrix as necessary
        if (matrix_.size() < m + 1) {
            matrix_.resize(m + 1, matrix_[0]);
        }
        if (matrix_[0].size() < n + 1) {
            for (auto& mat : matrix_) {
                mat.resize(n + 1);
            }
        }
        // The top row and left column are prefixes that can be reached by
        // insertions and deletions alone
        unsigned int i, j;
        for (i = 1;  i <= m; ++i) {
            matrix_[i][0] = i;
        }
        for (j = 1; j <= n; ++j) {
            matrix_[0][j] = j;
        }
        // Fill in the rest of the matrix
        for (j = 1; j <= n; ++j) {
            for (i = 1; i <= m; ++i) {
                unsigned int substitution_cost = s[i - 1] == t[j - 1] ? 0 : 1;
                matrix_[i][j] =
                    min3(matrix_[i - 1][j] + 1,                 // Deletion
                    matrix_[i][j - 1] + 1,                      // Insertion
                    matrix_[i - 1][j - 1] + substitution_cost); // Substitution
            }
        }
        return matrix_[m][n];
    }
};
 1
Author: Martin Broadhurst, 2017-01-16 09:56:58

Functor também pode ser usado para simular a definição de uma função local dentro de uma função. Consulte a perguntae Outra.

Mas um functor local não pode aceder fora das variáveis automáticas. A função lambda (C++11) é uma solução melhor.

 0
Author: Shawn Xie, 2017-05-23 12:34:53

Eu "descobri" um uso muito interessante de functores: eu os USO Quando Não tenho um bom nome para um método, como um functor é um método Sem Nome; -)

 -9
Author: JChMathae, 2011-02-16 13:29:25