Ponteiro de variável de membro
-
21-12-2019 - |
Pergunta
Para uma determinada estrutura:
struct foo
{
void fooFunc(){}
int fooVar = 0;
};
Posso criar uma chamada wapper para a função: std::mem_fn( &foo::fooFunc )
de modo que eu possa passá-lo para outro método e chamá-lo em um objeto.
Quero saber se existe um wrapper de chamada semelhante, mas para variáveis de membro.
Por exemplo, estou usando um ponteiro para uma variável de membro aqui, mas gostaria de usar um wrapper de chamada:
void bar( std::function< void( foo ) > funcPtr, int foo::* varPtr )
{
foo myFoo;
funcPtr( myFoo );
foo.*varPtr = 13;
}
Solução
N. B.Nada na sua pergunta é do STL (que é uma biblioteca da década de 1990), std::function
e std::mem_fn
fazem parte da Biblioteca Padrão C++, o que não é a mesma coisa.
std::mem_fn
suporta funções-membro e variáveis-membro, então você pode fazer isso apenas para acessar a variável-membro e defini-la:
foo f;
std::function<int&(foo&)> var( std::mem_fn( &foo::fooVar ) );
var(f) = 1;
Outras dicas
Além das funções de membro, std::mem_fn
também pode agrupar membros de dados e permitir acesso de leitura a eles.Então funciona o seguinte:
void print_fooVar(foo& f, std::function<int(foo)> varAccess)
{
std::cout << varAccess(f) << std::endl;
}
foo f;
print_fooVar(f, std::mem_fn(&foo::fooVar)); // prints 0
Como JonathanWakely menciona nos comentários, você pode usar o tipo (não especificado) retornado por mem_fn
para definir o membro de dados.
foo f;
std::mem_fn(&foo::fooVar)(f) = 13;
Ou transformá-lo em um std::function
usar
void bar( foo& f, std::function<int&(foo&)> fooVarSet )
{
fooVarSet(f) = 26;
}
Se tudo o que você está procurando é uma maneira de gerar um callable para definir o fooVar
membro de dados e não usando std::mem_fn
especificamente para fazer isso, você também pode realizar o trabalho usando uma expressão lambda.
void bar( foo& f, std::function<void(foo)> funcPtr,
std::function<void(foo&, int)> fooVarSet )
{
funcPtr( f );
fooVarSet(f, 13);
}
foo f;
bar(f, std::mem_fn(&foo::fooFunc), [](foo& f, int i) {f.fooVar = i;});