Consider the following class:
template <size_t nb_rows, size_t nb_cols>
class ButtonMatrix
{
public:
ButtonMatrix(const pin_t (&rowPins)[nb_rows], const pin_t (&colPins)[nb_cols], const uint8_t (&addresses)[nb_rows][nb_cols])
: rowPins(rowPins), colPins(colPins), addresses(addresses) { }
private:
const pin_t (&rowPins)[nb_rows], (&colPins)[nb_cols];
const uint8_t (&addresses)[nb_rows][nb_cols];
};
I can initialize it using arrays like this:
const pin_t rows[2] = {0, 1};
const pin_t cols[2] = {2, 3};
const uint8_t addresses[2][2] = {
{0x01, 0x02},
{0x03, 0x04}
};
ButtonMatrix<2, 2> bm(rows, cols, addresses);
And it works just fine. However, I'd like to be able to initialize it using brace-enclosed initializer lists as well:
ButtonMatrix<2, 2> bm({0, 1}, {2, 3}, addresses);
It compiles without problems, but it obviously doesn't work, because the rowPins and colPins only live for the duration of the constructor, and cannot be used in the other methods of the class.
To get around this, I could copy the contents of rowPins and colPins:
template <size_t nb_rows, size_t nb_cols>
class ButtonMatrix
{
public:
ButtonMatrix(const pin_t (&rowPins)[nb_rows], const pin_t (&colPins)[nb_cols], const uint8_t (&addresses)[nb_rows][nb_cols])
: addresses(addresses) {
memcpy(this->rowPins, rowPins, sizeof(rowPins[0]) * nb_rows);
memcpy(this->colPins, colPins, sizeof(colPins[0]) * nb_cols);
}
private:
pin_t rowPins[nb_rows], colPins[nb_cols];
const uint8_t (&addresses)[nb_rows][nb_cols];
};
This way, I can either initialize it with array reference or with brace-enclosed initializer list.
The only drawback is that when using array references, there's two copies of the same data. The target platform is Arduino, so I'd like to keep memory usage to a minimum.
Is there a way to determine whether an initializer list was used to initialize it, and if so, dynamically memory for the array?
Something along these lines: C++ overload constructor with const array and initializer_list
It would be nice to have compile-time errors if the dimensions of the initializer lists don't match nb_rows and nb_cols, so that rules out std::initializer_list (please correct me if I'm wrong).
addressesbeing multidimensional severely complicates dynamic allocation. Can this be a flat array of sizenb_rows * nb_colsinstead?rowPinsandcolPinsif you do allocate the memory dynamically?