我怎样才能 std::bind 一个用户提供的函数到 std::function 类型的成员变量?
How can I std::bind a user-provided function to a member variable of type std::function?
我有一个带有成员变量std::function customCallback
的class,我需要让用户自定义它的行为。 customCallback
应将 const std::array<int, N>&
和 int
作为输入,以及 return 和 std::array<int, N>
(其中 N
是模板参数)。
我目前正在使用std::bind
来实现,但我不明白为什么编译失败。我错过了什么?
由于原始代码涉及继承和模板,因此我在我的最小可重现示例 (live code here) 中也包含了继承和模板。
用户应该能够使用构造函数或成员函数来设置自定义行为。
base.h
:
#include <array>
#include <functional>
template <std::size_t N>
class BaseClass {
public:
virtual std::array<int, N> CustomBehavior(const std::array<int, N>& user_array, int user_number) = 0;
protected:
std::array<int, N> my_array = {0, 0};
};
derived.h
:
#include <base.h>
#include <cstddef>
template <std::size_t N>
class DerivedClass : public BaseClass<N> {
public:
DerivedClass() = default;
DerivedClass(std::function<std::array<int, N>(const std::array<int, N>&, int)> custom_f)
: customCallback(std::bind(custom_f, std::ref(std::placeholders::_1), std::placeholders::_2)) {}
void SetCustomBehavior(std::function<std::array<int, N>(const std::array<int>&, int)> custom_f) {
customCallback = std::bind(custom_f, std::ref(std::placeholders::_1), std::placeholders::_2);
}
std::array<int, N> CustomBehavior(const std::array<int, N>& user_array, int user_number) override {
if (customCallback)
this->my_array = customCallback(user_array, user_number);
return this->my_array;
}
private:
std::function<std::array<int, N>(const std::array<int, N>&, int)> customCallback;
};
main.cpp
:
#include <derived.h>
#include <cassert>
static constexpr std::size_t MySize = 2;
std::array<int, MySize> my_behavior(const std::array<int, MySize>& input_array, int a) {
return {a * input_array[0], a * input_array[1]};
}
int main() {
std::array<int, MySize> my_array = {1, 1};
// Default constructor (COMPILES)
DerivedClass<MySize> foo_1; // OK
std::array<int, MySize> bar_1 = foo_1.CustomBehavior(my_array, 2);
assert(bar_1[0] == 0 && bar_1[1] == 0);
// Custom constructor (ERROR)
DerivedClass<MySize> foo_2(my_behavior); // COMPILATION ERROR
std::array<int, MySize> bar_2 = foo_2.CustomBehavior(my_array, 2);
assert(bar_2[0] == 2 && bar_2[1] == 2);
// Custom behavior set later on (ERROR)
DerivedClass<MySize> foo_3; // OK
foo_3.SetCustomBehavior(my_behavior); // COMPILATION ERROR
std::array<int, MySize> bar_3 = foo_3.CustomBehavior(my_array, 2);
assert(bar_3[0] == 2 && bar_3[1] == 2);
return 0;
}
我没有包括整个编译错误,因为它相当长,但是可以看到 live code here。
好吧,对于初学者来说,您遇到的第一个错误是 Derived::SetCustomBehavior()
中 std::array<int>
上的错误:
error: wrong number of template arguments (1, should be 2)
您在 std::ref(std::placeholders::_1)
上也有错误,应该只是 std::placeholders::_1
.
修复这两个错误,然后代码编译并运行(使用更正的断言):
也就是说,在这种情况下您实际上根本不需要 std::bind()
。您的 custom_f
参数与 customCallback
成员的类型相同,因此只需将 custom_f
按原样分配给 customCallback
.
帮自己一个忙 - 为您的 std::function
和 std::array
类型创建类型别名,使您的代码更具可读性。
试试这个:
base.h
#include <array>
#include <functional>
#include <cstddef>
template<std::size_t N>
using intArray = std::array<int, N>;
template<std::size_t N>
using callbackType =
std::function<intArray<N>(const intArray<N>&, int)>;
template <std::size_t N>
class BaseClass {
public:
virtual intArray<N> CustomBehavior(const intArray<N>& user_array, int user_number) = 0;
protected:
intArray<N> my_array = {0, 0};
};
derived.h:
#include "base.h"
template <std::size_t N>
class DerivedClass : public BaseClass<N> {
public:
DerivedClass() = default;
DerivedClass(callbackType<N> custom_f)
: customCallback(std::move(custom_f))
{}
void SetCustomBehavior(callbackType<N> custom_f) {
customCallback = std::move(custom_f);
}
intArray<N> CustomBehavior(const intArray<N>& user_array, int user_number) override {
if (customCallback)
this->my_array = customCallback(user_array, user_number);
return this->my_array;
}
private:
callbackType<N> customCallback;
};
main.cpp:
#include "derived.h"
#include <cassert>
static constexpr std::size_t MySize = 2;
using myIntArray = intArray<MySize>;
myIntArray my_behavior(const myIntArray& input_array, int a) {
return {a * input_array[0], a * input_array[1]};
}
int main() {
myIntArray my_array = {1, 1};
// Default constructor
DerivedClass<MySize> foo_1;
myIntArray bar_1 = foo_1.CustomBehavior(my_array, 2);
assert(bar_1[0] == 0 && bar_1[1] == 0);
// Custom constructor
DerivedClass<MySize> foo_2(my_behavior);
myIntArray bar_2 = foo_2.CustomBehavior(my_array, 2);
assert(bar_2[0] == 2 && bar_2[1] == 2);
// Custom behavior set later on
DerivedClass<MySize> foo_3;
foo_3.SetCustomBehavior(my_behavior);
myIntArray bar_3 = foo_3.CustomBehavior(my_array, 2);
assert(bar_3[0] == 2 && bar_3[1] == 2);
return 0;
}
我有一个带有成员变量std::function customCallback
的class,我需要让用户自定义它的行为。 customCallback
应将 const std::array<int, N>&
和 int
作为输入,以及 return 和 std::array<int, N>
(其中 N
是模板参数)。
我目前正在使用std::bind
来实现,但我不明白为什么编译失败。我错过了什么?
由于原始代码涉及继承和模板,因此我在我的最小可重现示例 (live code here) 中也包含了继承和模板。
用户应该能够使用构造函数或成员函数来设置自定义行为。
base.h
:
#include <array>
#include <functional>
template <std::size_t N>
class BaseClass {
public:
virtual std::array<int, N> CustomBehavior(const std::array<int, N>& user_array, int user_number) = 0;
protected:
std::array<int, N> my_array = {0, 0};
};
derived.h
:
#include <base.h>
#include <cstddef>
template <std::size_t N>
class DerivedClass : public BaseClass<N> {
public:
DerivedClass() = default;
DerivedClass(std::function<std::array<int, N>(const std::array<int, N>&, int)> custom_f)
: customCallback(std::bind(custom_f, std::ref(std::placeholders::_1), std::placeholders::_2)) {}
void SetCustomBehavior(std::function<std::array<int, N>(const std::array<int>&, int)> custom_f) {
customCallback = std::bind(custom_f, std::ref(std::placeholders::_1), std::placeholders::_2);
}
std::array<int, N> CustomBehavior(const std::array<int, N>& user_array, int user_number) override {
if (customCallback)
this->my_array = customCallback(user_array, user_number);
return this->my_array;
}
private:
std::function<std::array<int, N>(const std::array<int, N>&, int)> customCallback;
};
main.cpp
:
#include <derived.h>
#include <cassert>
static constexpr std::size_t MySize = 2;
std::array<int, MySize> my_behavior(const std::array<int, MySize>& input_array, int a) {
return {a * input_array[0], a * input_array[1]};
}
int main() {
std::array<int, MySize> my_array = {1, 1};
// Default constructor (COMPILES)
DerivedClass<MySize> foo_1; // OK
std::array<int, MySize> bar_1 = foo_1.CustomBehavior(my_array, 2);
assert(bar_1[0] == 0 && bar_1[1] == 0);
// Custom constructor (ERROR)
DerivedClass<MySize> foo_2(my_behavior); // COMPILATION ERROR
std::array<int, MySize> bar_2 = foo_2.CustomBehavior(my_array, 2);
assert(bar_2[0] == 2 && bar_2[1] == 2);
// Custom behavior set later on (ERROR)
DerivedClass<MySize> foo_3; // OK
foo_3.SetCustomBehavior(my_behavior); // COMPILATION ERROR
std::array<int, MySize> bar_3 = foo_3.CustomBehavior(my_array, 2);
assert(bar_3[0] == 2 && bar_3[1] == 2);
return 0;
}
我没有包括整个编译错误,因为它相当长,但是可以看到 live code here。
好吧,对于初学者来说,您遇到的第一个错误是 Derived::SetCustomBehavior()
中 std::array<int>
上的错误:
error: wrong number of template arguments (1, should be 2)
您在 std::ref(std::placeholders::_1)
上也有错误,应该只是 std::placeholders::_1
.
修复这两个错误,然后代码编译并运行(使用更正的断言):
也就是说,在这种情况下您实际上根本不需要 std::bind()
。您的 custom_f
参数与 customCallback
成员的类型相同,因此只需将 custom_f
按原样分配给 customCallback
.
帮自己一个忙 - 为您的 std::function
和 std::array
类型创建类型别名,使您的代码更具可读性。
试试这个:
base.h
#include <array>
#include <functional>
#include <cstddef>
template<std::size_t N>
using intArray = std::array<int, N>;
template<std::size_t N>
using callbackType =
std::function<intArray<N>(const intArray<N>&, int)>;
template <std::size_t N>
class BaseClass {
public:
virtual intArray<N> CustomBehavior(const intArray<N>& user_array, int user_number) = 0;
protected:
intArray<N> my_array = {0, 0};
};
derived.h:
#include "base.h"
template <std::size_t N>
class DerivedClass : public BaseClass<N> {
public:
DerivedClass() = default;
DerivedClass(callbackType<N> custom_f)
: customCallback(std::move(custom_f))
{}
void SetCustomBehavior(callbackType<N> custom_f) {
customCallback = std::move(custom_f);
}
intArray<N> CustomBehavior(const intArray<N>& user_array, int user_number) override {
if (customCallback)
this->my_array = customCallback(user_array, user_number);
return this->my_array;
}
private:
callbackType<N> customCallback;
};
main.cpp:
#include "derived.h"
#include <cassert>
static constexpr std::size_t MySize = 2;
using myIntArray = intArray<MySize>;
myIntArray my_behavior(const myIntArray& input_array, int a) {
return {a * input_array[0], a * input_array[1]};
}
int main() {
myIntArray my_array = {1, 1};
// Default constructor
DerivedClass<MySize> foo_1;
myIntArray bar_1 = foo_1.CustomBehavior(my_array, 2);
assert(bar_1[0] == 0 && bar_1[1] == 0);
// Custom constructor
DerivedClass<MySize> foo_2(my_behavior);
myIntArray bar_2 = foo_2.CustomBehavior(my_array, 2);
assert(bar_2[0] == 2 && bar_2[1] == 2);
// Custom behavior set later on
DerivedClass<MySize> foo_3;
foo_3.SetCustomBehavior(my_behavior);
myIntArray bar_3 = foo_3.CustomBehavior(my_array, 2);
assert(bar_3[0] == 2 && bar_3[1] == 2);
return 0;
}