Skip to content

Instantly share code, notes, and snippets.

@gatchamix
Last active July 25, 2018 21:14
Show Gist options
  • Save gatchamix/95bfa7a51a39e54c239c720e6d94f79d to your computer and use it in GitHub Desktop.
Save gatchamix/95bfa7a51a39e54c239c720e6d94f79d to your computer and use it in GitHub Desktop.
simple matrix container using C++17 (original idea courtesy of jdmarsh)
#include <utility>
#include <cstddef>
#include <array>
#include <type_traits>
//
template <class T, std::size_t Rows, std::size_t Cols = Rows>
struct matrix
{
static auto constexpr rows = Rows;
static auto constexpr cols = Cols;
static auto constexpr size = rows * cols;
private:
template <class Input, std::size_t... Is>
auto constexpr init__(Input&& in, std::index_sequence<Is...>)
{ return std::array{ static_cast<T>(in[Is])... }; }
public:
template <class... Ts, std::size_t N,
std::enable_if_t<sizeof...(Ts) == Rows && N == Cols>* = nullptr>
constexpr matrix(Ts(&&...in)[N])
: data_{ init__(std::move(in), std::make_index_sequence<N>{})... }
{}
constexpr matrix() = default;
auto constexpr& operator[](std::size_t const i)
{ return data_[i]; }
auto constexpr& operator[](std::size_t const i) const
{ return data_[i]; }
auto constexpr& front()
{ return data_[0][0]; }
auto constexpr& front() const
{ return data_[0][0]; }
auto constexpr& back()
{ return data_[rows - 1][cols - 1]; }
auto constexpr& back() const
{ return data_[rows - 1][cols - 1]; }
private:
std::array<std::array<T, Cols>, Rows> data_;
};
template <class... Ts, std::size_t N>
matrix(Ts(&&..._)[N])
-> matrix<std::common_type_t<Ts...>, sizeof...(Ts), N>;
//
template <class... Args>
auto constexpr make_matrix(Args&&... args)
{ return matrix{ static_cast<Args&&>(args)... }; }
template <auto... _, class... Ts, std::size_t N,
std::enable_if_t<sizeof...(_) == 0>* = nullptr>
auto constexpr make_matrix(Ts(&&...in)[N])
{ return true; }
template <class T, auto... _, class... Ts, std::size_t N,
std::enable_if_t<sizeof...(_) == 0>* = nullptr>
auto constexpr make_matrix(Ts(&&...in)[N])
{ return matrix<T, sizeof...(Ts), N>{ std::move(in)... }; }
template <class T, std::size_t Rows, std::size_t Cols = Rows, auto... _,
class... Ts, std::size_t N, std::enable_if_t<sizeof...(_) == 0>* = nullptr>
auto constexpr make_matrix(Ts(&&...in)[N])
{ return matrix<T, Rows, Cols>{ std::move(in)... }; }
template <class T, std::size_t Rows, std::size_t Cols = Rows>
auto constexpr make_matrix()
{ return matrix<T, Rows, Cols>{}; }
//
auto main(int argc, char **argv)
-> int
{
// construction
auto constexpr a1 = matrix{ { 1.0, 2.0 }, { 3.0, 4.0 } };
//auto constexpr a2 = matrix<double>{ { 1.0, 2.0 }, { 3.0, 4.0 } }; // P1021 ?
//auto constexpr a3 = matrix<int>({ 1.0, 2.0 }, { 3.0, 4.0 }); // P1021 ?
auto constexpr a4 = matrix<double, 2>{ { 1.0, 2.0 }, { 3.0, 4.0 } };
auto constexpr a5 = matrix<int, 2>{ { 1.0, 2.0 }, { 3.0, 4.0 } };
auto constexpr a6 = matrix<double, 2>{};
auto constexpr a7 = matrix<double, 2, 2>{ { 1.0, 2.0 }, { 3.0, 4.0 } };
auto constexpr a8 = matrix<int, 2, 2>{ { 1.0, 2.0 }, { 3.0, 4.0 } };
auto constexpr a9 = matrix<double, 2, 2>{};
// make_matrix - remove after P1021 ?
auto constexpr b1 = make_matrix({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b2 = make_matrix<double>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b3 = make_matrix<int>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b4 = make_matrix<double, 2>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b5 = make_matrix<int, 2>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b6 = make_matrix<double, 2>();
auto constexpr b7 = make_matrix<double, 2, 2>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b8 = make_matrix<int, 2, 2>({ 1.0, 2.0 }, { 3.0, 4.0 });
auto constexpr b9 = make_matrix<double, 2, 2>();
// copy-construction
auto constexpr c1 = matrix{ a1 };
auto constexpr c2 = make_matrix(a1);
// move-construction
auto constexpr d1 = matrix{ matrix<double, 2>{} };
auto constexpr d2 = make_matrix(matrix<double, 2>{});
// copy-assignment
auto e = matrix<double, 2>{};
e = a1;
// move-assignment
auto f = matrix<double, 2>{};
f = matrix<double, 2>{};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment