Quero que meu modelo aceite lambdas com diferentes números de parâmetros e seja capaz de lidar com eles.
No código abaixo, o template process
pega o objeto callable (função), mas não sabe se o lambda passado pega argumentos ou não. Posso de alguma forma verificar isso no template e fazer a respectiva chamada?
void process(auto fn) {
[[maybe_unused]] float res = fn(2.0f);
// Is there a chance to make something like:
// float res = takes-no-args<fn>() ? fn() : fn(2.0f);
// do something with res...
}
int main() {
// This is the default usage
process([](float arg) { return arg; });
// I want to be able to make such a call
process([]() { return 1.0f; });
// Possible, but verbose workaround
process([](float) { return 1.0f; });
}
Uma solução alternativa simples seria sempre passar o lambda com a mesma assinatura e ignorar o argumento fornecido, mas isso é muito prolixo no caso de muitos argumentos.
O objetivo é manter o código do cliente o mais simples e limpo possível.
Sim,
takes-no-args<fn>()
existe na família destd::is_invocable
características de tipo, então você pode verificar sefn
é invocável sem argumentos usando constexpr-if assim:Para algo mais complexo do que um
float
, você pode não querer construí-lo primeiro, então você pode, por exemplo, usar um lambda invocado imediatamente para evitar isso: