Gostaria de saber se seria possível chamar callbacks em um container com apenas uma instrução, sem lambda (é uma espécie de exercício).
Eu tentei com std::invoke
. Aqui está meu código:
#include <algorithm>
#include <functional>
#include <iostream>
int main()
{
std::function<void(void)> foo = []() { std::cout << "Foo !"; };
std::function<void(void)> bar = []() { std::cout << "Bar !"; };
const std::vector<std::function<void(void)>> callbacks = { foo, bar };
std::for_each(callbacks.cbegin(), callbacks.cend(), std::invoke);
return 0;
}
Mas recebo muitos erros na compilação:
main.cpp: In function ‘int main()’:
main.cpp:12:22: error: no matching function for call to ‘for_each(std::vector >::const_iterator, std::vector >::const_iterator, )’
12 | std::for_each(callbacks.cbegin(), callbacks.cend(), std::invoke);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/algorithm:62,
from main.cpp:1:
/usr/include/c++/11/bits/stl_algo.h:3814:5: note: candidate: ‘template _Funct std::for_each(_IIter, _IIter, _Funct)’
3814 | for_each(_InputIterator __first, _InputIterator __last, _Function __f)
| ^~~~~~~~
/usr/include/c++/11/bits/stl_algo.h:3814:5: note: template argument deduction/substitution failed:
main.cpp:12:22: note: couldn’t deduce template parameter ‘_Funct’
12 | std::for_each(callbacks.cbegin(), callbacks.cend(), std::invoke);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/11/algorithm:74,
from main.cpp:1:
/usr/include/c++/11/pstl/glue_algorithm_defs.h:42:1: note: candidate: ‘template __pstl::__internal::__enable_if_execution_policy<_ExecutionPolicy, void> std::for_each(_ExecutionPolicy&&, _ForwardIterator, _ForwardIterator, _Function)’
42 | for_each(_ExecutionPolicy&& __exec, _ForwardIterator __first, _ForwardIterator __last, _Function __f);
| ^~~~~~~~
/usr/include/c++/11/pstl/glue_algorithm_defs.h:42:1: note: template argument deduction/substitution failed:
main.cpp:12:22: note: candidate expects 4 arguments, 3 provided
12 | std::for_each(callbacks.cbegin(), callbacks.cend(), std::invoke);
| ~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Call Stack
# Function File:Line
Local Variables
Variable Value
Registers
Register Value
Display Expressions
Expression Value
Breakpoints and Watchpoints
# Description
Tentei também com a linha:
std::for_each(callbacks.cbegin(), callbacks.cend(), std::invoke<void(void)>);
mas ainda tenho problemas:
In file included from /usr/include/c++/11/algorithm:62,
from main.cpp:1:
/usr/include/c++/11/bits/stl_algo.h: In instantiation of ‘_Funct std::for_each(_IIter, _IIter, _Funct) [with _IIter = __gnu_cxx::__normal_iterator<const std::function<void()>*, std::vector<std::function<void()> > >; _Funct = void (*)(void (&&)())]’:
main.cpp:12:15: required from here
/usr/include/c++/11/bits/stl_algo.h:3820:12: error: invalid initialization of reference of type ‘void (&&)()’ from expression of type ‘const std::function’
3820 | __f(*__first);
| ~~~^~~~~~~~~~
Não é possível fazer isso sem um lambda porque
std::invoke
(como muitas outras funções emstd
) não permite pegar seu endereço.Você pode ver mais informações sobre isso aqui: Posso pegar o endereço de uma função definida na biblioteca padrão? .
Caso ajude, veja como fazer isso com um lambda:
Para cada elemento no intervalo (que é uma função de retorno de chamada no seu caso), o lambda será chamado com ele como um argumento.
Você pode então usar
std::invoke
para chamar o elemento da função de retorno de chamada:Saída:
Demonstração ao vivo