Reputation: 5353
I have a Register
function which takes a std::function<void(const uint8_t* data, size_t len)>
as a parameter. I want to use the member function of an object as the target.
I found this question according to which the answer is to use std::bind
to bind the first first argument (the implicit this
pointer) to the actual object pointer and then use it as the std::function
argument.
This however doesn't work anymore in neither C++11, C++14 nor C++17?
Consider the following test program.
#include <iostream>
#include <cstdint>
#include <functional>
void Register(std::function<void(const uint8_t* data, size_t len)> func) {
//Dummy - directly call into function
func(nullptr, 0);
}
class TestClass {
public:
void TestRegister() {
Register(
std::bind(&TestClass::TestTarget, this, std::placeholders::_1)
);
}
void TestTarget(const uint8_t* data, size_t len) {
(void) data;
(void) len;
std::cout << "Hello there" << std::endl;
}
};
int main() {
TestClass testObj;
testObj.TestRegister();
return 0;
}
When compiling for -std=c++17
this throws a rather cryptic error message (I have no idea what it's trying to say here with Wrong number of arguments for pointer-to-member
):
In file included from /home/max/Documents/TestingFunctions/main.cpp:3:0:
/usr/include/c++/7/functional: In instantiation of ‘struct std::_Bind_check_arity<void (TestClass::*)(const unsigned char*, long unsigned int), TestClass*, const std::_Placeholder<1>&>’:
/usr/include/c++/7/functional:854:12: required from ‘struct std::_Bind_helper<false, void (TestClass::*)(const unsigned char*, long unsigned int), TestClass*, const std::_Placeholder<1>&>’
/usr/include/c++/7/functional:875:5: required by substitution of ‘template<class _Func, class ... _BoundArgs> typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type std::bind(_Func&&, _BoundArgs&& ...) [with _Func = void (TestClass::*)(const unsigned char*, long unsigned int); _BoundArgs = {TestClass*, const std::_Placeholder<1>&}]’
/home/max/Documents/TestingFunctions/main.cpp:14:78: required from here
/usr/include/c++/7/functional:841:7: error: static assertion failed: Wrong number of arguments for pointer-to-member
static_assert(_Varargs::value
^~~~~~~~~~~~~
/home/max/Documents/TestingFunctions/main.cpp: In member function ‘void TestClass::TestRegister()’:
/home/max/Documents/TestingFunctions/main.cpp:14:26: error: could not convert ‘std::bind(_Func&&, _BoundArgs&& ...) [with _Func = void (TestClass::*)(const unsigned char*, long unsigned int); _BoundArgs = {TestClass*, const std::_Placeholder<1>&}; typename std::_Bind_helper<std::__is_socketlike<_Func>::value, _Func, _BoundArgs ...>::type = std::_Bind<void (TestClass::*(TestClass*, std::_Placeholder<1>))(const unsigned char*, long unsigned int)>](((TestClass*)this), std::placeholders::_1)’ from ‘std::_Bind_helper<false, void (TestClass::*)(const unsigned char*, long unsigned int), TestClass*, const std::_Placeholder<1>&>::type {aka std::_Bind<void (TestClass::*(TestClass*, std::_Placeholder<1>))(const unsigned char*, long unsigned int)>}’ to ‘std::function<void(const unsigned char*, long unsigned int)>’
std::bind(&TestClass::TestTarget, this, std::placeholders::_1)
~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Replacing the TestRegister
function with one that does the exact same thing in a lambda expression compiles and runs without problems.
void TestRegister() {
Register(
[this](const uint8_t* data, size_t len) {
TestTarget(data, len);
}
);
}
Question: Why does the std::bind
approach from the linked question not work? Was this feature removed or do I have an error in my code?
Upvotes: 4
Views: 3112
Reputation: 38539
Your function Register
expects a function with two parameters, but you try to pass to it a function with one placeholded parameter.
void TestRegister() {
Register(
std::bind(&TestClass::TestTarget, this, std::placeholders::_1, std::placeholders::_2)
);
}
Upvotes: 8
Reputation: 10425
Your function takes two parameters, while you are only passing one placeholder.
std::bind(&TestClass::TestTarget, this, std::placeholders::_1, std::placeholders::_2);
Upvotes: 3