From 48b24cf83b22866158a2723eaa779d19f54bb4de Mon Sep 17 00:00:00 2001
From: Philip Trettner <Philip.Trettner@rwth-aachen.de>
Date: Mon, 28 Jan 2019 15:36:27 +0100
Subject: [PATCH] deduction guides for C++17

---
 CMakeLists.txt                       |  4 ++++
 README.md                            |  6 +++++-
 src/tg/detail/functions/transpose.hh | 16 ++++++++++++++++
 src/tg/types/mat.hh                  | 19 +++++++++++++++++++
 src/tg/types/pos.hh                  | 13 +++++++++++++
 src/tg/types/size.hh                 | 13 +++++++++++++
 src/tg/types/vec.hh                  | 13 +++++++++++++
 7 files changed, 83 insertions(+), 1 deletion(-)
 create mode 100644 src/tg/detail/functions/transpose.hh

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 32b02e3..ac362bc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -14,3 +14,7 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES})
 add_library(typed-geometry STATIC ${SOURCES})
 
 target_include_directories(typed-geometry PUBLIC "src")
+
+if (CMAKE_CXX_STANDARD GREATER_EQUAL 17)
+    target_compile_definitions(typed-geometry PUBLIC TG_SUPPORT_CXX17)
+endif()
diff --git a/README.md b/README.md
index 4f2cf63..a881025 100644
--- a/README.md
+++ b/README.md
@@ -70,6 +70,11 @@ TODO: splines
 * if still ambiguous: faster changing parameters go last (e.g. `coordinates(tri, point)` or `mix(a, b, t)`)
 
 
+### C++ 17 Features
+
+* deduction guides: `auto v = tg::vec(1.0f, 2.0f, 3.0f)`
+* structured binding: `auto [x, y, z] = tg::vec3(...)`
+
 ## Dependencies
 
 None.
@@ -79,4 +84,3 @@ None.
 * Benchmark how compile times are affected by includes / templates
 * Add tests that verify optimal assembly generated
 * Fractional and bigint data types
-* Deduction guides
diff --git a/src/tg/detail/functions/transpose.hh b/src/tg/detail/functions/transpose.hh
new file mode 100644
index 0000000..95d97cf
--- /dev/null
+++ b/src/tg/detail/functions/transpose.hh
@@ -0,0 +1,16 @@
+#pragma once
+
+#include "../../types/mat.hh"
+
+namespace tg
+{
+template <int C, int R, class T>
+constexpr mat<R, C, T> transpose(mat<C, R, T> const& m)
+{
+    mat<R, C, T> r;
+    for (auto y = 0; y < R; ++y)
+        for (auto x = 0; x < C; ++x)
+            r[y][x] = m[x][y];
+    return r;
+}
+} // namespace tg
diff --git a/src/tg/types/mat.hh b/src/tg/types/mat.hh
index 298f1bb..b5df679 100644
--- a/src/tg/types/mat.hh
+++ b/src/tg/types/mat.hh
@@ -90,6 +90,20 @@ using umat4x4 = mat<4, 4, u32>;
 
 // ======== IMPLEMENTATION ========
 
+/*
+ * Memory layout of a 4x4:
+ *  0  4  8 12
+ *  1  5  9 13
+ *  2  6 10 14
+ *  3  7 11 15
+ *
+ * i.e. col-major
+ *
+ * matCxR (cols x rows)
+ *
+ * mat3x4 has no translational part
+ * mat4x3 has no projective part
+ */
 template <int C, int R, class ScalarT>
 struct mat
 {
@@ -97,8 +111,13 @@ struct mat
     using col_t = vec<R, ScalarT>;
     using transpose_t = mat<C, R, ScalarT>;
 
+    static constexpr shape<2> shape = make_shape(C, R);
+
     col_t m[R];
 
+    constexpr col_t& operator[](int i) { return m[i]; }
+    constexpr col_t const& operator[](int i) const { return m[i]; }
+
     mat() = default;
 };
 
diff --git a/src/tg/types/pos.hh b/src/tg/types/pos.hh
index 561618a..902f043 100644
--- a/src/tg/types/pos.hh
+++ b/src/tg/types/pos.hh
@@ -190,7 +190,20 @@ struct pos<4, ScalarT>
 template <class ScalarT>
 constexpr pos<4, ScalarT> pos<4, ScalarT>::zero = {ScalarT(0), ScalarT(0), ScalarT(0), ScalarT(0)};
 
+// comparison operators
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(pos, pos, bool, operator==, &&, ==);
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(pos, pos, bool, operator!=, ||, !=);
 
+// deduction guides
+#ifdef TG_SUPPORT_CXX17
+template <class T>
+pos(T const& x)->pos<1, T>;
+template <class T>
+pos(T const& x, T const& y)->pos<2, T>;
+template <class T>
+pos(T const& x, T const& y, T const& z)->pos<3, T>;
+template <class T>
+pos(T const& x, T const& y, T const& z, T const& w)->pos<4, T>;
+#endif
+
 } // namespace tg
diff --git a/src/tg/types/size.hh b/src/tg/types/size.hh
index 0cb7c40..7366080 100644
--- a/src/tg/types/size.hh
+++ b/src/tg/types/size.hh
@@ -167,6 +167,19 @@ struct size<4, ScalarT>
     }
 };
 
+// comparison operators
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(size, size, bool, operator==, &&, ==);
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(size, size, bool, operator!=, ||, !=);
+
+// deduction guides
+#ifdef TG_SUPPORT_CXX17
+template <class T>
+size(T const& x)->size<1, T>;
+template <class T>
+size(T const& x, T const& y)->size<2, T>;
+template <class T>
+size(T const& x, T const& y, T const& z)->size<3, T>;
+template <class T>
+size(T const& x, T const& y, T const& z, T const& w)->size<4, T>;
+#endif
 } // namespace tg
diff --git a/src/tg/types/vec.hh b/src/tg/types/vec.hh
index 2b8b7bb..a9e7a07 100644
--- a/src/tg/types/vec.hh
+++ b/src/tg/types/vec.hh
@@ -307,7 +307,20 @@ constexpr vec<4, ScalarT> vec<4, ScalarT>::unit_z = {ScalarT(0), ScalarT(0), Sca
 template <class ScalarT>
 constexpr vec<4, ScalarT> vec<4, ScalarT>::unit_w = {ScalarT(0), ScalarT(0), ScalarT(0), ScalarT(1)};
 
+// comparison operators
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(vec, vec, bool, operator==, &&, ==);
 TG_IMPL_DEFINE_REDUCTION_OP_BINARY(vec, vec, bool, operator!=, ||, !=);
 
+// deduction guides
+#ifdef TG_SUPPORT_CXX17
+template <class T>
+vec(T const& x)->vec<1, T>;
+template <class T>
+vec(T const& x, T const& y)->vec<2, T>;
+template <class T>
+vec(T const& x, T const& y, T const& z)->vec<3, T>;
+template <class T>
+vec(T const& x, T const& y, T const& z, T const& w)->vec<4, T>;
+#endif
+
 } // namespace tg
-- 
GitLab