Thread overview
Deducing types from member function template
Dec 02, 2006
Li Jie
Dec 04, 2006
%u JScott
Dec 04, 2006
Oskar Linde
December 02, 2006
I want to write a Matrix class, a c++ version looks like:

[code]
template <class T, int R, int C>
class Matrix
{
};

template <class T, int R, int C, int C1>
Matrix<T,R,C1> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,C,C1>& rhs)
{
    return Matrix<T,R,C1>();
}

int main()
{
    Matrix<int,3,4> m1;
    Matrix<int,4,3> m2;
    Matrix<int,3,3> m3 = m1 * m2;
    Matrix<int,2,3> m4;
    // m1 * m4;  <== MUST compile fail

    return 0;
}
[/code]

It can be compiled. D version:

[code]
class Matrix(T, int R, int C){
    static assert(R > 0 && C > 0);

    Matrix!(T,R,C1) opMul(int C1)(Matrix!(T,C,C1) rhs){
        return null;
    }
}


int main()
{
    Matrix!(int,3,4) m1;
    Matrix!(int,4,3) m2;
    // auto m3 = m1 * m2;  <== NEED compile success
    Matrix!(int,3,3) m3 = m1.opMul!(3)(m2);
    Matrix!(int,2,3) m4;
    // m1 * m4;  <== MUST compile fail

    return 0;
}
[/code]

"m1 * m2" can't be compiled:

matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) does not
match any template declaration
matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) cannot
deduce template function from argument types (Matrix)
matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) does not
match any template declaration
matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) cannot
deduce template function from argument types (Matrix)


I must write "m1.opMul!(3)(m2)". Can you help me?
December 04, 2006
I think as of right now the template args of a function must match exactly to the function args for it to be implicitly called, like so:

void func(T)(T t){}

I'm writting some matrix math routines myself so I tried to find a solution / work around, but came up empty. I think it's a reasonable feture request. Or maybe the ability to do something like this:

Matrix!(T,R,C2) opMul(Matrix!(T,R,int C2) M){}
December 04, 2006
Li Jie wrote:
> I want to write a Matrix class, a c++ version looks like:
> 
> [code]
> template <class T, int R, int C>
> class Matrix
> {
> };
> 
> template <class T, int R, int C, int C1>
> Matrix<T,R,C1> operator* (const Matrix<T,R,C>& lhs, const Matrix<T,C,C1>& rhs)
> {
>     return Matrix<T,R,C1>();
> }
> 
> int main()
> {
>     Matrix<int,3,4> m1;
>     Matrix<int,4,3> m2;
>     Matrix<int,3,3> m3 = m1 * m2;
>     Matrix<int,2,3> m4;
>     // m1 * m4;  <== MUST compile fail
> 
>     return 0;
> }
> [/code]
> 
> It can be compiled. D version:
> 
> [code]
> class Matrix(T, int R, int C){
>     static assert(R > 0 && C > 0);
> 
>     Matrix!(T,R,C1) opMul(int C1)(Matrix!(T,C,C1) rhs){
>         return null;
>     }
> }
> 
> 
> int main()
> {
>     Matrix!(int,3,4) m1;
>     Matrix!(int,4,3) m2;
>     // auto m3 = m1 * m2;  <== NEED compile success
>     Matrix!(int,3,3) m3 = m1.opMul!(3)(m2);
>     Matrix!(int,2,3) m4;
>     // m1 * m4;  <== MUST compile fail
> 
>     return 0;
> }
> [/code]
> 
> "m1 * m2" can't be compiled:
> 
> matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) does not
> match any template declaration
> matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) cannot
> deduce template function from argument types (Matrix)
> matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) does not
> match any template declaration
> matrix.d(14): template matrix.Matrix!(int,3,4).Matrix.opMul(int C1) cannot
> deduce template function from argument types (Matrix)
> 
> 
> I must write "m1.opMul!(3)(m2)". Can you help me?

This is indeed a limitation of D's implicit template instantiation deduction. Try this instead:

class Matrix(T, int R, int C){
    static assert(R > 0 && C > 0);
    const r = R;
    const c = C;

    Matrix!(T,R,M.c) opMul(M)(M rhs){
        static assert(C == M.r,
                      "Matrix inner dimensions must agree for *");
        return null;
    }
}

/Oskar