/******************************************************************************
Welcome to GDB Online.
GDB online is an online compiler and debugger tool for C, C++, Python, PHP, Ruby,
C#, VB, Perl, Swift, Prolog, Javascript, Pascal, HTML, CSS, JS
Code, Compile, Run and Debug online from anywhere in world.
*******************************************************************************/
#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <type_traits>
// mocked functionality of the library with the C interface
typedef void(*c_callback_type)(void* context);
std::list<std::pair<c_callback_type, void*>> g_callbacks;
void execute_callbacks()
{
for(const auto& callback : g_callbacks)
{
callback.first(callback.second);
}
}
// C interface: C-style callback
void c_add_callback(void(*callback)(void* context), void* context)
{
g_callbacks.emplace_back(callback, context);
}
// wrapper class that wraps the C interface in C++
// this wrapper shall be stateless, i. e. shall not have any non-const members
class CppWrapper
{
public:
// C++ callable parameter
template<typename Function>
void AddCallback(Function& function)
{
c_callbacks_.push_back
([](void* context)
{
(*reinterpret_cast<Function*>(context))();
}
);
c_add_callback
(c_callbacks_.back()
, reinterpret_cast<void*>(&function)
);
}
private:
// storage of c callbacks
std::list<void(*)(void*)> c_callbacks_;
};
void function()
{
std::cout << "function called" << std::endl;
}
struct Functor
{
void operator()() const
{
std::cout << "functor called" << std::endl;
}
};
int main()
{
CppWrapper wrapper;
// function as callable
wrapper.AddCallback
(function
);
// functor as callable
Functor functor;
wrapper.AddCallback
(functor
);
// lambda as callable
int result = 0;
auto lambda = [&result]()
{
result = 1;
std::cout << "lambda called" << std::endl;
};
wrapper.AddCallback
(lambda
);
// test callback execution
execute_callbacks();
return 0;
}