【问题标题】:C++17 Cannot use std::bind to produce a std::functionC++17 不能使用 std::bind 生成 std​​::function
【发布时间】:2018-10-29 01:05:55
【问题描述】:

我有一个Register 函数,它以std::function<void(const uint8_t* data, size_t len)> 作为参数。我想使用对象的成员函数作为目标。

我找到this question,据此答案是使用std::bind将第一个参数(隐式this指针)绑定到实际对象指针,然后将其用作std::function参数。

但是,这在 C++11、C++14 和 C++17 中都不再起作用了吗?

考虑以下测试程序。

#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;
}

当为-std=c++17 编译时,这会抛出一个相当神秘的错误消息(我不知道它在这里用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)
                 ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

TestRegister 函数替换为在 lambda 表达式中执行完全相同操作的函数可以编译并运行而不会出现问题。

void TestRegister() {
    Register(
            [this](const uint8_t* data, size_t len) {
                TestTarget(data, len);
            }
    );
}

问题:为什么链接问题中的std::bind 方法不起作用?这个功能是被删除了还是我的代码有错误?

【问题讨论】:

  • 第二个占位符在哪里?

标签: c++ functional-programming c++17 stdbind


【解决方案1】:

您的函数Register 需要一个带有两个参数的函数,但您尝试向它传递一个带有一个占位参数的函数。

void TestRegister() {
     Register(
             std::bind(&TestClass::TestTarget, this, std::placeholders::_1, std::placeholders::_2)
     );
}

【讨论】:

  • 啊现在我明白了!我虽然使用this, std::placeholders::_1,但我将this 作为(隐藏的)第一个函数参数传递!但是我必须在我没有指定直接参数的每个地方都使用占位符。谢谢,这清除了它。 (我可以在 3 分钟内接受这个答案)
【解决方案2】:

你的函数有两个参数,而你只传递一个占位符。

std::bind(&TestClass::TestTarget, this, std::placeholders::_1, std::placeholders::_2);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 1970-01-01
    • 2015-06-15
    • 2016-12-18
    • 2013-04-16
    • 2019-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多