functors polimórficos em std :: for_each
-
03-07-2019 - |
Pergunta
Eu estou tentando usar STL algoritmo for_each sem proliferando modelos em todo o meu código. std :: for_each quer classe MyFunctor instanciar por valor, mas não pode desde o seu resumo. Eu criei uma classe do adaptador functor que passa um ponteiro ao redor e então derefernces-lo quando necessário.
Minha pergunta:
Será que o STL ou aumentar já tem uma tal classe do adaptador? Eu não quero ter que reinventar a roda!
struct MyFunctor {
virtual ~MyFunctor() {}
virtual void operator()(int a) = 0;
}
namespace {
template<typename FunctorType, typename OperandType> struct
FunctorAdapter
{
FunctorAdapter(FunctorType* functor) : mFunctor(functor) {}
void operator()(OperandType& subject)
{
(*mFunctor)(subject);
}
FunctorType* mFunctor;
}; }
void applyToAll(MyFunctor &f) {
FunctorHelper<MyFunctor, int> tmp(&f);
std::for_each(myvector.begin(), myvector.end(), tmp); }
Cheers,
Dave
Solução
tr1 :: ref pode ajudá-lo aqui --- que está destinado a ser um invólucro de referência para que você possa passar objetos normais por referência para ligar ou função objetos (mesmo os abstratos) por referência aos algoritmos padrão.
// requires TR1 support from your compiler / standard library implementation
#include <functional>
void applyToAll(MyFunctor &f) {
std::for_each(
myvector.begin(),
myvector.end(),
std::tr1::ref(f)
);
}
No entanto, note que compiladores sem apoio decltype pode Rejeitar passando uma referência a um tipo abstrato ... então este código pode não ser compilado até obter suporte C ++ 0x.
Outras dicas
Você pode usar os adaptadores de função (e seus calços) a partir functional
.
#include <functional>
using namespace std;
for_each( vec.begin(), vec.end(), :mem_fun_ptr( &MyClass::f ) );
Se o seu recipiente contém ponteiros-a-objetos, uso mem_fun_ptr
, uso mem_fun
mais. Ao lado destes, existem wrappers para funções membro que levam um argumento: mem_fun1_ptr
e mem_fun1
@Evan: na verdade, você poderia chamar a função de membro com o mesmo argumento para cada objeto. O primeiro argumento dos invólucros mem_fun1
é o ponteiro this
, o segundo é o argumento da função membro:
for_each( vec.begin(), vec.end(), bind2nd( mem_fun_ptr( &MyClass::f ), 1 ) );
Com mais argumentos, torna-se mais legível para criar um loop de si mesmo, ou criar um functor personalizado que tem variáveis ??de membro const que representam os argumentos.
por que não usar BOOST_FOREACH?
Parece que você poderia beneficiar boost :: Função .
Se bem me lembro, é um cabeçalho única biblioteca também, por isso é fácil de ir buscá-la com ele.
E sobre esquecendo todo o embrulho do ponteiro functor e, em vez uso
bind(functor_pointer,mem_fun1(&MyFunctor::operator());
como o functor? Dessa forma, você não precisa se preocupar em gerenciar a cópia em qualquer forma ou meio.
Com base na resposta de @ xtofl, já que a matriz contém int do e não "este" ponteiros, eu acho que o encantamento correto é
class MyClass
{
virtual void process(int number) = 0;
};
MyClass *instance = ...;
for_each( vec.begin(), vec.end(), binder1st(instance, mem_fun_ptr(&MyClass::process) );
A única diferença em relação de @ xtofl código é binder1st em vez de binder2nd. binder2nd permite que você passe teh mesmo número a várias "este" ponteiros. binder1st permite passar vários números a um ponteiro "este".