From 89957b37b37073ddfaab6ac0212c73e0e64cdffb Mon Sep 17 00:00:00 2001
From: Philip Trettner <Philip.Trettner@rwth-aachen.de>
Date: Wed, 30 Jan 2019 05:44:58 +0100
Subject: [PATCH] fixed mixed deduction guides

---
 src/tg/detail/macros.hh        | 16 +++---
 src/tg/detail/scalar_traits.hh |  2 +-
 src/tg/types/pos.hh            | 95 ++++++++++++++++------------------
 src/tg/types/size.hh           | 74 ++++++++++++--------------
 4 files changed, 86 insertions(+), 101 deletions(-)

diff --git a/src/tg/detail/macros.hh b/src/tg/detail/macros.hh
index ac3302c..e6aa9aa 100644
--- a/src/tg/detail/macros.hh
+++ b/src/tg/detail/macros.hh
@@ -73,23 +73,23 @@
     }
 
 #define TG_IMPL_DEFINE_BINARY_OP_SCALAR_RIGHT(TYPE, OP)                                                                               \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarB>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarB>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<1, ScalarR> operator OP(TYPE<1, ScalarA> const& a, ScalarB const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a.TG_IMPL_MEMBER(TYPE, 0)) OP ScalarR(b)};                                                                    \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarB>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarB>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<2, ScalarR> operator OP(TYPE<2, ScalarA> const& a, ScalarB const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a.TG_IMPL_MEMBER(TYPE, 0)) OP ScalarR(b), ScalarR(a.TG_IMPL_MEMBER(TYPE, 1)) OP ScalarR(b)};                  \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarB>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarB>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<3, ScalarR> operator OP(TYPE<3, ScalarA> const& a, ScalarB const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a.TG_IMPL_MEMBER(TYPE, 0)) OP ScalarR(b), ScalarR(a.TG_IMPL_MEMBER(TYPE, 1)) OP ScalarR(b),                   \
                 ScalarR(a.TG_IMPL_MEMBER(TYPE, 2)) OP ScalarR(b)};                                                                    \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarB>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarB>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<4, ScalarR> operator OP(TYPE<4, ScalarA> const& a, ScalarB const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a.TG_IMPL_MEMBER(TYPE, 0)) OP ScalarR(b), ScalarR(a.TG_IMPL_MEMBER(TYPE, 1)) OP ScalarR(b),                   \
@@ -97,23 +97,23 @@
     }
 
 #define TG_IMPL_DEFINE_BINARY_OP_SCALAR_LEFT(TYPE, OP)                                                                                \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarA>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarA>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<1, ScalarR> operator OP(ScalarA const& a, TYPE<1, ScalarB> const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 0))};                                                                    \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarA>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarA>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<2, ScalarR> operator OP(ScalarA const& a, TYPE<2, ScalarB> const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 0)), ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 1))};                  \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarA>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarA>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<3, ScalarR> operator OP(ScalarA const& a, TYPE<3, ScalarB> const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 0)), ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 1)),                   \
                 ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 2))};                                                                    \
     }                                                                                                                                 \
-    template <class ScalarA, class ScalarB, class ScalarR = promoted_scalar<ScalarA, ScalarB>, class = enable_if<is_scalar<ScalarA>>> \
+    template <class ScalarA, class ScalarB, class = enable_if<is_scalar<ScalarA>>, class ScalarR = promoted_scalar<ScalarA, ScalarB>> \
     constexpr TYPE<4, ScalarR> operator OP(ScalarA const& a, TYPE<4, ScalarB> const& b)                                               \
     {                                                                                                                                 \
         return {ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 0)), ScalarR(a) OP ScalarR(b.TG_IMPL_MEMBER(TYPE, 1)),                   \
diff --git a/src/tg/detail/scalar_traits.hh b/src/tg/detail/scalar_traits.hh
index e4cc2d6..5c45e3e 100644
--- a/src/tg/detail/scalar_traits.hh
+++ b/src/tg/detail/scalar_traits.hh
@@ -187,7 +187,7 @@ template <class A, class B>
 struct promoted_scalar_t
 {
     static constexpr int bitmax(int a, int b) { return a > b ? a : b; }
-    using type = scalar<promoted_scalar_base<A, B>, bitmax(scalar_bit_width<A>, scalar_bit_width<B>)>;
+    using type = scalar<promoted_scalar_base<scalar_base_type<A>, scalar_base_type<B>>, bitmax(scalar_bit_width<A>, scalar_bit_width<B>)>;
 };
 template <class A, class B>
 using promoted_scalar = typename promoted_scalar_t<A, B>::type;
diff --git a/src/tg/types/pos.hh b/src/tg/types/pos.hh
index 0013ab2..533cd1d 100644
--- a/src/tg/types/pos.hh
+++ b/src/tg/types/pos.hh
@@ -1,6 +1,7 @@
 #pragma once
 
 #include "../detail/macros.hh"
+#include "../detail/scalar_traits.hh"
 #include "../detail/utility.hh"
 #include "scalar.hh"
 
@@ -47,19 +48,17 @@ struct pos
 template <class ScalarT>
 struct pos<1, ScalarT>
 {
-    using scalar_t = ScalarT;
-
     static const pos zero;
 
-    scalar_t x = static_cast<scalar_t>(0);
+    ScalarT x = static_cast<ScalarT>(0);
 
-    constexpr scalar_t& operator[](int i) { return (&x)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&x)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&x)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&x)[i]; }
 
     constexpr pos() = default;
-    constexpr pos(scalar_t v) : x(v) {}
+    constexpr pos(ScalarT v) : x(v) {}
     template <int D, class T, class = enable_if<D >= 1>>
-    constexpr explicit pos(pos<D, T> const& v, scalar_t = ScalarT(0)) : x(ScalarT(v.x))
+    constexpr explicit pos(pos<D, T> const& v, ScalarT = ScalarT(0)) : x(ScalarT(v.x))
     {
     }
     template <int D, class T>
@@ -74,25 +73,23 @@ constexpr pos<1, ScalarT> pos<1, ScalarT>::zero = {ScalarT(0)};
 template <class ScalarT>
 struct pos<2, ScalarT>
 {
-    using scalar_t = ScalarT;
-
-    scalar_t x = static_cast<scalar_t>(0);
-    scalar_t y = static_cast<scalar_t>(0);
+    ScalarT x = static_cast<ScalarT>(0);
+    ScalarT y = static_cast<ScalarT>(0);
 
     static const pos zero;
 
-    constexpr scalar_t& operator[](int i) { return (&x)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&x)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&x)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&x)[i]; }
 
     constexpr pos() = default;
-    constexpr explicit pos(scalar_t v) : x(v), y(v) {}
-    constexpr pos(scalar_t x, scalar_t y) : x(x), y(y) {}
+    constexpr explicit pos(ScalarT v) : x(v), y(v) {}
+    constexpr pos(ScalarT x, ScalarT y) : x(x), y(y) {}
     template <int D, class T, class = enable_if<D >= 2>>
-    constexpr explicit pos(pos<D, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y))
+    constexpr explicit pos(pos<D, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y))
     {
     }
     template <class T>
-    constexpr explicit pos(pos<1, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill)
+    constexpr explicit pos(pos<1, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill)
     {
     }
     template <int D, class T>
@@ -107,30 +104,28 @@ constexpr pos<2, ScalarT> pos<2, ScalarT>::zero = {ScalarT(0), ScalarT(0)};
 template <class ScalarT>
 struct pos<3, ScalarT>
 {
-    using scalar_t = ScalarT;
-
-    scalar_t x = static_cast<scalar_t>(0);
-    scalar_t y = static_cast<scalar_t>(0);
-    scalar_t z = static_cast<scalar_t>(0);
+    ScalarT x = static_cast<ScalarT>(0);
+    ScalarT y = static_cast<ScalarT>(0);
+    ScalarT z = static_cast<ScalarT>(0);
 
     static const pos zero;
 
-    constexpr scalar_t& operator[](int i) { return (&x)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&x)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&x)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&x)[i]; }
 
     constexpr pos() = default;
-    constexpr explicit pos(scalar_t v) : x(v), y(v), z(v) {}
-    constexpr pos(scalar_t x, scalar_t y, scalar_t z) : x(x), y(y), z(z) {}
+    constexpr explicit pos(ScalarT v) : x(v), y(v), z(v) {}
+    constexpr pos(ScalarT x, ScalarT y, ScalarT z) : x(x), y(y), z(z) {}
     template <int D, class T, class = enable_if<D >= 3>>
-    constexpr explicit pos(pos<D, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z))
+    constexpr explicit pos(pos<D, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z))
     {
     }
     template <class T>
-    constexpr explicit pos(pos<2, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(fill)
+    constexpr explicit pos(pos<2, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(fill)
     {
     }
     template <class T>
-    constexpr explicit pos(pos<1, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill), z(fill)
+    constexpr explicit pos(pos<1, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill), z(fill)
     {
     }
     template <int D, class T, class = enable_if<D <= 3>>
@@ -145,35 +140,33 @@ constexpr pos<3, ScalarT> pos<3, ScalarT>::zero = {ScalarT(0), ScalarT(0), Scala
 template <class ScalarT>
 struct pos<4, ScalarT>
 {
-    using scalar_t = ScalarT;
-
     static const pos zero;
 
-    scalar_t x = static_cast<scalar_t>(0);
-    scalar_t y = static_cast<scalar_t>(0);
-    scalar_t z = static_cast<scalar_t>(0);
-    scalar_t w = static_cast<scalar_t>(0);
+    ScalarT x = static_cast<ScalarT>(0);
+    ScalarT y = static_cast<ScalarT>(0);
+    ScalarT z = static_cast<ScalarT>(0);
+    ScalarT w = static_cast<ScalarT>(0);
 
-    constexpr scalar_t& operator[](int i) { return (&x)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&x)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&x)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&x)[i]; }
 
     constexpr pos() = default;
-    constexpr explicit pos(scalar_t v) : x(v), y(v), z(v), w(v) {}
-    constexpr pos(scalar_t x, scalar_t y, scalar_t z, scalar_t w) : x(x), y(y), z(z), w(w) {}
+    constexpr explicit pos(ScalarT v) : x(v), y(v), z(v), w(v) {}
+    constexpr pos(ScalarT x, ScalarT y, ScalarT z, ScalarT w) : x(x), y(y), z(z), w(w) {}
     template <int D, class T, class = enable_if<D >= 4>>
-    constexpr explicit pos(pos<D, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z)), w(ScalarT(v.w))
+    constexpr explicit pos(pos<D, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z)), w(ScalarT(v.w))
     {
     }
     template <class T>
-    constexpr explicit pos(pos<3, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z)), w(fill)
+    constexpr explicit pos(pos<3, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(ScalarT(v.z)), w(fill)
     {
     }
     template <class T>
-    constexpr explicit pos(pos<2, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(fill), w(fill)
+    constexpr explicit pos(pos<2, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(ScalarT(v.y)), z(fill), w(fill)
     {
     }
     template <class T>
-    constexpr explicit pos(pos<1, T> const& v, scalar_t fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill), z(fill), w(fill)
+    constexpr explicit pos(pos<1, T> const& v, ScalarT fill = ScalarT(0)) : x(ScalarT(v.x)), y(fill), z(fill), w(fill)
     {
     }
     template <int D, class T, class = enable_if<D <= 4>>
@@ -191,14 +184,14 @@ 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>;
+template <class A>
+pos(A const& x)->pos<1, A>;
+template <class A, class B>
+pos(A const& x, B const& y)->pos<2, promoted_scalar<A, B>>;
+template <class A, class B, class C>
+pos(A const& x, B const& y, C const& z)->pos<3, promoted_scalar<A, promoted_scalar<B, C>>>;
+template <class A, class B, class C, class D>
+pos(A const& x, B const& y, C const& z, D const& w)->pos<4, promoted_scalar<promoted_scalar<A, B>, promoted_scalar<C, D>>>;
 #endif
 
 } // namespace tg
diff --git a/src/tg/types/size.hh b/src/tg/types/size.hh
index d7c21af..a5bcf8d 100644
--- a/src/tg/types/size.hh
+++ b/src/tg/types/size.hh
@@ -48,15 +48,13 @@ struct size
 template <class ScalarT>
 struct size<1, ScalarT>
 {
-    using scalar_t = ScalarT;
+    ScalarT width = static_cast<ScalarT>(0);
 
-    scalar_t width = static_cast<scalar_t>(0);
-
-    constexpr scalar_t& operator[](int i) { return (&width)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&width)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&width)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&width)[i]; }
 
     constexpr size() = default;
-    constexpr size(scalar_t v) : width(v) {}
+    constexpr size(ScalarT v) : width(v) {}
     template <int D, class T, class = enable_if<D >= 1>>
     constexpr explicit size(size<D, T> const& v) : width(ScalarT(v.width))
     {
@@ -75,17 +73,15 @@ struct size<1, ScalarT>
 template <class ScalarT>
 struct size<2, ScalarT>
 {
-    using scalar_t = ScalarT;
-
-    scalar_t width = static_cast<scalar_t>(0);
-    scalar_t height = static_cast<scalar_t>(0);
+    ScalarT width = static_cast<ScalarT>(0);
+    ScalarT height = static_cast<ScalarT>(0);
 
-    constexpr scalar_t& operator[](int i) { return (&width)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&width)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&width)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&width)[i]; }
 
     constexpr size() = default;
-    constexpr explicit size(scalar_t v) : width(v), height(v) {}
-    constexpr size(scalar_t width, scalar_t height) : width(width), height(height) {}
+    constexpr explicit size(ScalarT v) : width(v), height(v) {}
+    constexpr size(ScalarT width, ScalarT height) : width(width), height(height) {}
     template <int D, class T, class = enable_if<D >= 2>>
     constexpr explicit size(size<D, T> const& v) : width(ScalarT(v.width)), height(ScalarT(v.height))
     {
@@ -104,18 +100,16 @@ struct size<2, ScalarT>
 template <class ScalarT>
 struct size<3, ScalarT>
 {
-    using scalar_t = ScalarT;
+    ScalarT width = static_cast<ScalarT>(0);
+    ScalarT height = static_cast<ScalarT>(0);
+    ScalarT depth = static_cast<ScalarT>(0);
 
-    scalar_t width = static_cast<scalar_t>(0);
-    scalar_t height = static_cast<scalar_t>(0);
-    scalar_t depth = static_cast<scalar_t>(0);
-
-    constexpr scalar_t& operator[](int i) { return (&width)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&width)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&width)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&width)[i]; }
 
     constexpr size() = default;
-    constexpr explicit size(scalar_t v) : width(v), height(v), depth(v) {}
-    constexpr size(scalar_t width, scalar_t height, scalar_t depth) : width(width), height(height), depth(depth) {}
+    constexpr explicit size(ScalarT v) : width(v), height(v), depth(v) {}
+    constexpr size(ScalarT width, ScalarT height, ScalarT depth) : width(width), height(height), depth(depth) {}
     template <int D, class T, class = enable_if<D >= 3>>
     constexpr explicit size(size<D, T> const& v) : width(ScalarT(v.width)), height(ScalarT(v.height)), depth(ScalarT(v.depth))
     {
@@ -134,19 +128,17 @@ struct size<3, ScalarT>
 template <class ScalarT>
 struct size<4, ScalarT>
 {
-    using scalar_t = ScalarT;
-
-    scalar_t width = static_cast<scalar_t>(0);
-    scalar_t height = static_cast<scalar_t>(0);
-    scalar_t depth = static_cast<scalar_t>(0);
-    scalar_t w = static_cast<scalar_t>(0);
+    ScalarT width = static_cast<ScalarT>(0);
+    ScalarT height = static_cast<ScalarT>(0);
+    ScalarT depth = static_cast<ScalarT>(0);
+    ScalarT w = static_cast<ScalarT>(0);
 
-    constexpr scalar_t& operator[](int i) { return (&width)[i]; }
-    constexpr scalar_t const& operator[](int i) const { return (&width)[i]; }
+    constexpr ScalarT& operator[](int i) { return (&width)[i]; }
+    constexpr ScalarT const& operator[](int i) const { return (&width)[i]; }
 
     constexpr size() = default;
-    constexpr explicit size(scalar_t v) : width(v), height(v), depth(v), w(v) {}
-    constexpr size(scalar_t width, scalar_t height, scalar_t depth, scalar_t w) : width(width), height(height), depth(depth), w(w) {}
+    constexpr explicit size(ScalarT v) : width(v), height(v), depth(v), w(v) {}
+    constexpr size(ScalarT width, ScalarT height, ScalarT depth, ScalarT w) : width(width), height(height), depth(depth), w(w) {}
     template <int D, class T, class = enable_if<D >= 4>>
     constexpr explicit size(size<D, T> const& v) : width(ScalarT(v.width)), height(ScalarT(v.height)), depth(ScalarT(v.depth)), w(ScalarT(v.w))
     {
@@ -168,13 +160,13 @@ 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>;
+template <class A>
+size(A const& x)->size<1, A>;
+template <class A, class B>
+size(A const& x, B const& y)->size<2, promoted_scalar<A, B>>;
+template <class A, class B, class C>
+size(A const& x, B const& y, C const& z)->size<3, promoted_scalar<A, promoted_scalar<B, C>>>;
+template <class A, class B, class C, class D>
+size(A const& x, B const& y, C const& z, D const& w)->size<4, promoted_scalar<promoted_scalar<A, B>, promoted_scalar<C, D>>>;
 #endif
 } // namespace tg
-- 
GitLab