I have a class with a member variable std::function customCallback
, and I need to let the user customize its behavior. customCallback
should take as input a const std::array<int, N>&
and a int
, and return a std::array<int, N>
(where N
is a template parameter).
I am currently using std::bind
to achieve this, but I can't understand why the compilation fails. What am I missing?
Since the original code involves inheritance and templates, I am including inheritance and templates in my minimal reproducible example (live code here) as well.
The user should be able to use both the constructor OR a member function to set the custom behavior.
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;
}
I am not including the whole compilation error since it's fairly long, but it can be seen live code here.