0

Problem

I have a Matrix class that is able to do some math. It holds its data in a double nested std::array as a variable. I have a constructor that takes an array reference as a variadic template. I did this so i could add some SFINAE more easily (omitted here).

#include <array>

template <std::size_t N, std::size_t M, typename T>
class Matrix{
  public:

    template <typename... TArgs>
    Matrix(TArgs const(&&... rows)[M]) {
        // ??
    }

  // ...

  private:
    std::array<std::array<T,M>, N> data;
};

Question

How can i initialize the double nested array inside the constructor?

5
  • How should we determine N? Just size of that pack? Commented Dec 15, 2020 at 16:52
  • 1
    You initialize members in the initializer list, not in the constructor body. Commented Dec 15, 2020 at 16:54
  • yeah, it's the size of the pack. N and M are known at compile time. basically the all sizes (i.e. matrix dimensions) are fixed which should make it easier to initialize... Commented Dec 15, 2020 at 16:55
  • godbolt here: godbolt.org/z/GP9369 Commented Dec 15, 2020 at 16:57
  • I don't understand const && usage here. They typically come apart. Commented Dec 15, 2020 at 17:26

2 Answers 2

2

With the not shown constraint than sizeof..(TArgs) == N and types are T, you might store address of rows in array pointer and then work normally

template <typename... TArgs>
Matrix(TArgs const(&&... rows)[M]) {
    using Arr = const T (*)[M];
    const Arr args[N] = {&rows...}; // or const T (*args[N])[M] = {&rows...};

    for (std::size_t i = 0; i != N; ++i) {
        for (std::size_t j = 0; j != M; ++j) {
            data[i][j] = (*args[i])[j];
        }
    }
}

Demo

Sign up to request clarification or add additional context in comments.

Comments

2

With std::to_array that would be part of C++20, we could simply write:

template<std::size_t N, std::size_t M, typename T>
class Matrix {
public:
    template<typename... Args>
    Matrix(const Args(&... rows)[M]) : data{std::to_array(rows)...}
    {}

private:
    std::array<std::array<T, M>, N> data;
};

Until C++20 we can copy-paste to_array implementation from here, which will add a few more lines to this solution.

Simplified implementation:

template<std::size_t N, typename T, std::size_t... is>
std::array<T, N> to_array_impl(const T(& arr)[N], std::index_sequence<is...>) {
    return std::array<T, N>{arr[is]...};
}

template<std::size_t N, typename T>
std::array<T, N> to_array(const T(& arr)[N]) {
    return to_array_impl(arr, std::make_index_sequence<N>{});
}

With member list initialization you would be able to initialize const data, too.

1 Comment

unfortunately i have to use c++14. but i tried your simplified implementation of to_array and it works nicely

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.