How to directly bind a member function to a std :: function in Visual Studio 11?

I can easily associate member functions with std::function by wrapping them with a lambda expression with a header clause.

 class Class { Class() { Register([=](int n){ Function(n); }); } void Register(std::function<void(int)> Callback) { } void Function(int Number) { } }; 

But I want to link them directly, something like the following.

 // ... Register(&Class::Function); // ... 

I think according to the C ++ 11 standard, this should be supported. However, in Visual Studio 11, I get these compiler errors.

error C2440: 'newline': cannot convert from 'int' to 'Class *'

error C2647: '. * ': cannot dereference' void (__thiscall Class :: *) (int) 'to' int '

+15
source share
6 answers

I think according to the C ++ 11 standard, this should be supported

Not so, because the non-static member function has an implicit first parameter of type (cv-qualified) YourType* , so in this case it does not match void(int) . Therefore, std::bind is required:

 Register(std::bind(&Class::Function, PointerToSomeInstanceOfClass, _1)); 

for instance

 Class c; using namespace std::placeholders; // for _1, _2 etc. c.Register(std::bind(&Class::Function, &c, _1)); 

Change You mentioned that this needs to be called with the same instance of Class . In this case, you can use a simple non-member function:

 void (int n) foo { theClassInstance.Function(n); } 

then

 Class c; c.Register(foo); 
+33
source

According to Stefan T. Lawavey - "Avoid using bind (), ..., use lambdas." https://www.youtube.com/watch?v=zt7ThwVfap0&t=32m20s

In this case:

 Class() { Register([this](int n){ Function(n); }); } 
+27
source

You can use std::bind :

 using namespace std::placeholders; // For _1 in the bind call // ... Register(std::bind(&Class::Function, this, _1)); 
+8
source

With std::function and std::bind you can handle different functions of a class member the same way.

 #include <iostream> #include <functional> #include <vector> using namespace std; using namespace std::placeholders; class Foo { public: void foo(const string &msg) { cout << msg << '\n'; } }; class Bar { public: void bar(const string &msg, const string &suffix) { cout << msg << suffix << '\n'; } }; int main(int argc, char **argv) { Foo foo; Bar bar; vector<function<void (const string &msg)>> collection; collection.push_back(bind(&Foo::foo, &foo, _1)); collection.push_back(bind(&Bar::bar, &bar, _1, "bar")); for (auto f : collection) { f("foo"); } return 0; } 
+1
source

I have no idea what you are trying to do there, but I suppose I did here if this is what you are trying to do:

 #include <chrono> #include <iostream> #include <functional> auto measure = [](auto function, auto&&... parameters) -> decltype(function(parameters...)) { const std::chrono::steady_clock::time_point startTimePoint = std::chrono::steady_clock::now(); auto returnValue = function(parameters...); const std::chrono::steady_clock::time_point stopTimePoint = std::chrono::steady_clock::now(); const std::chrono::duration<double> timeSpan = std::chrono::duration_cast< std::chrono::duration<double>>(stopTimePoint - startTimePoint); std::cout << "Computation took " << timeSpan.count() << " seconds." << std::endl; return returnValue; }; class Test { public: int computation(double dummy) { std::cout << "Received " << dummy << ". Computing..." << std::endl; return 123; } }; int main(int, char**) { Test instance; auto func = std::bind(&Test::computation, &instance, std::placeholders::_1); int result = measure(func, 1.0); std::cout << "Result: " << result << std::endl; return 0; } 
0
source

In C ++ 17, you can use:

 Register([=](auto && ...args){ return Function(args...); }); 

which is nice, especially if the argument list is longer. Of course, the argument list of a member function must be compatible with std::function .

0
source

Source: https://habr.com/ru/post/947396/


All Articles