#include <array>
#include <cassert>
#include <cstddef>
#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};
};

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

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
    DerivedClass<MySize> foo_1; // OK
    std::array<int, MySize> bar_1 = foo_1.CustomBehavior(my_array, 2);
    assert(bar_1[0] == 2 && bar_1[1] == 2);

    // Custom constructor
    DerivedClass<MySize> foo_2(my_behavior); // COMPILATION ERROR
    std::array<int, MySize> bar_2 = foo_2.CustomBehavior(my_array, 2);
    assert(bar_1[0] == 2 && bar_1[1] == 2);

    // Default constructor with custom behavior set later on
    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_1[0] == 2 && bar_1[1] == 2);

    return 0;
}