'Generate const array of pointers to callback functions
I'd like to generate an array of N pointers to callbacks so I don't have to type them explicitly (LOC is not the issue here). I use C++17.
Here is what I have:
using Callback = void(*)();
auto constexpr N = 2;
const Callback callbacks[N] = {
[](){ auto i = 0; std::cout<<"callback " << i << "\n";},
[](){ auto i = 1; std::cout<<"callback " << i << "\n";}
};
callbacks[0]();
callbacks[N-1]();
Here is what I want:
const auto callbacks = generate_callbacks<N>(); // or generate_callbacks(N)
callbacks[i](); // cout<<"callback " << i << "\n";
I tried various ways, but I keep running into the problems with constant parameters even when they are from a constexpr function or variadic template.
If I try this:
Callback callbacks[N] = { };
for(int i=0;i<N;++i)
{
callbacks[i] = [i](){ std::cout<<"callback " << i << "\n";};
}
for(int i=0;i<N;++i)
{
callbacks[i]();
}
I get the following error:
main.cpp:91:66: error: cannot convert ‘main()::’ to ‘Callback {aka void (*)()}’ in assignment
callbacks[i] = [i](){ std::cout<<"callback " << i << "\n";};
If I make i static and leave out the capture it only uses the last value of i:
callback 2
callback 2
This is odd to me as capturing should be done at construction. Are the lambdas constructed after the loop exits?
As for the purpose. I want to apply this technique to generating interrupt handlers for microcontrollers. I can put the function pointers in the interrupt vector table directly. These functions have no parameters and I don't know a clean way to detect which interrupt source called the handler. I can write a handler for each interrupt, but I don't like repeating this code 6 times:
void handler0()
{
do_something(0);
}
Typing it as a lambda and/or using a template makes it a little cleaner, but I still have to type something N times. And if N changes I have to change multiple lines of code. This is not elegant.
Solution 1:[1]
The following compiles fine in both gcc and clang in C++17 mode. It uses some simple template metaprogramming to generate the sequence of callbacks.
#include <array>
#include <iostream>
using cb = void (*)();
template<int N>
inline auto fun()
{
std::cout << "callback: " << N << '\n';
}
template<int N>
void init(cb * arr)
{
arr[N] = &fun<N>;
init<N-1>(arr);
}
template<>
void init<0>(cb * arr)
{
arr[0] = &fun<0>;
}
template<int N>
struct callbacks
{
callbacks()
{
init<N>(cbs.data());
}
std::array<cb, N> cbs;
};
int main()
{
auto foo = callbacks<4>();
for (auto x = 0; x < 4; ++x)
{
foo.cbs[x]();
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Krzysiek Karbowiak |
