Eu estava tentando criar um vetor de lambda, mas falhou:
auto ignore = [&]() { return 10; }; //1
std::vector<decltype(ignore)> v; //2
v.push_back([&]() { return 100; }); //3
Até a linha 2, ele compila perfeitamente . Mas a linha 3 fornece erro de compilação :
erro: nenhuma função correspondente para chamada para 'std :: vector <main () :: <lambda () >> :: push_back (main () :: <lambda ()>)'
Não quero um vetor de ponteiros de função ou vetor de objetos de função. No entanto, o vetor de objetos de função que encapsulam expressões lambda reais funcionaria para mim. Isso é possível?
Respostas:
Cada lambda tem um tipo diferente - mesmo se eles tiverem a mesma assinatura. Você deve usar um contêiner de encapsulamento de tempo de execução, como
std::function
se você quiser fazer algo assim.por exemplo:
fonte
std::function<int()
, posso usar diferentes protótipos de função?vector
armazenamento de ambosstd::function
estd::string
?' E a resposta é a mesma: Não, porque esse não é o uso pretendido. Você pode usar uma classe de estilo 'variante' para realizar o apagamento de tipo suficiente para colocar coisas diferentes em um contêiner, enquanto inclui um método para um usuário determinar o tipo 'real' e, portanto, escolher o que fazer (por exemplo, como chamar) cada elemento ... mas, novamente, por que ir tão longe? Existe alguma razão real?Todas as expressões lambda têm um tipo diferente, mesmo se forem idênticas caractere por caractere . Você está colocando um lambda de um tipo diferente (porque é outra expressão) no vetor e isso obviamente não funcionará.
Uma solução é criar um vetor de
std::function<int()>
.Por outro lado, não é uma boa ideia usar
[&]
quando você não está capturando nada.fonte
()
de lambdas que não aceitam argumentos.Embora o que outros disseram seja relevante, ainda é possível declarar e usar um vetor de lambda, embora não seja muito útil:
Portanto, você pode armazenar qualquer número de lambdas lá, contanto que seja uma cópia / movimentação de
lambda
!fonte
Se seu lambda não tem estado, ou seja,
[](...){...}
C ++ 11 permite que ele se transforme em um ponteiro de função. Em teoria, um compilador compatível com C ++ 11 seria capaz de compilar isso:fonte
auto ignore = *[] { return 10; };
fariaignore
umint(*)()
.explicit
, a desreferenciação de uma expressão lambda é válida e desreferencia a referência do ponteiro resultante da conversão. Em seguida, o uso deauto
transforma essa referência em um ponteiro. (Usandoauto&
ouauto&&
teria mantido a referência.)()
intencional ou acidental?Você pode usar uma função de geração de lambda (atualizada com a correção sugerida por Nawaz):
Mas acho que você basicamente fez sua própria aula neste momento. Caso contrário, se os lambdas tiverem caputres / args completamente diferentes, etc., você provavelmente terá que usar uma tupla.
fonte
lambda_gen
que pode ser, por sua vez, um lambda. No entanto,auto a = lambda_gen(1);
faz uma chamada desnecessária, que pode ser evitada se escrevermos issodecltype(lambda_gen(1))
.decltype
é avaliada , então a chamada não é realmente feita. É o mesmo caso comsizeof
também. Além disso, este código não funcionará em C ++ 11, mesmo se você adicionar o tipo de retorno final !!Cada lambda é um tipo diferente. Você deve usar em
std::tuple
vez destd::vector
.fonte