Most examples don't clearly show how to create a std::function with a static class method that takes an object instance as the first parameter.
I would like to take a static class method that takes an object instance as the first parameter and create a new function that can be used as a C-style callback function and has access to an object instance.
I seem to have tried everything. I took the example here and tried to refactor it to my use case with no luck by using a similar examples here.
See more up-to-date example below
#include <functional>
#include <iostream>
struct Foo
{
Foo(int me) : m_me(me) {}
static int foo_static(Foo* f, int a, int b) { return f->m_me + a + b; }
int m_me;
};
int main()
{
Foo f(4);
using std::placeholders::_1;
std::function<int(int,int)> new_func = std::bind(&Foo::foo_static, &f, _1);
std::cout << new_func(3, 4) << std::endl;
}
EDIT
Forgot compiler output
$ c++ main.cpp -std=c++14
main.cpp:25:30: error: no viable conversion from '__bind<int (*)(Foo *, int, int), Foo *, const std::__1::placeholders::__ph<1> &>' to
'std::function<int (int, int)>'
std::function<int(int,int)> new_funct = std::bind(&Foo::foo_static, &f, _1);
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional:1627:5: note: candidate constructor not
viable: no known conversion from '__bind<int (*)(Foo *, int, int), Foo *, const std::__1::placeholders::__ph<1> &>' to 'std::nullptr_t'
(aka 'nullptr_t') for 1st argument
function(nullptr_t) _NOEXCEPT : __f_(0) {}
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional:1628:5: note: candidate constructor not
viable: no known conversion from '__bind<int (*)(Foo *, int, int), Foo *, const std::__1::placeholders::__ph<1> &>' to
'const std::__1::function<int (int, int)> &' for 1st argument
function(const function&);
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional:1629:5: note: candidate constructor not
viable: no known conversion from '__bind<int (*)(Foo *, int, int), Foo *, const std::__1::placeholders::__ph<1> &>' to
'std::__1::function<int (int, int)> &&' for 1st argument
function(function&&) _NOEXCEPT;
^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include/c++/v1/functional:1631:5: note: candidate template
ignored: requirement '__callable<__bind<int (*)(Foo *, int, int), Foo *, const __ph<1> &> >::value' was not satisfied [with _Fp =
std::__1::__bind<int (*)(Foo *, int, int), Foo *, const std::__1::placeholders::__ph<1> &>]
function(_Fp);
^
1 error generated.
Here's a bit more detail on what I'm trying to accomplish. The m_callback is what I'm trying to setup. I could push what I need in the callback into the ClientData but I like the Command structure to hold on to it's data and not have to create a new structure to pass as the ClientData per command.
#include <functional>
#include <iostream>
#include <string>
typedef void (* callback) (Client* client, ClientData* client_data);
struct Command
{
int execute() = 0;
}
struct Search : Command
{
enum SearchType { kType1, kType2 };
Search(Logger log, std::string query, SearchType type) : m_log(log), m_callback(), m_query(query), m_typ(type)
{
m_callback = // create callback
}
int execute(Client* client, ClientData* client_data)
{
client->query(client_data, m_callback, m_query, m_type);
}
static int my_callback(Foo* f, Client* client, ClientData* client_data);
Logger& m_log;
callback m_callback;
std::string m_query;
SearchType m_type;
// other data I want in the callback that isn't passed in client_data
};
int main()
{
Logger log;
Search search(log, "some search", Search::kType1);
Client client;
ClientData client_data;
search.execute(&client, client_data);
}
So I figured out what I was doing wrong with the std::bind
but now I need to convert that to the C-style callback I need to work with.