Last active
July 25, 2018 21:14
-
-
Save gatchamix/95bfa7a51a39e54c239c720e6d94f79d to your computer and use it in GitHub Desktop.
simple matrix container using C++17 (original idea courtesy of jdmarsh)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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