How to specify an arbitrary template argument for a function parameter?

时间:2019-04-16 23:23:46

标签: c++ templates

I wasn't sure how to articulate what I'm asking so hopefully some code will make it clear. I'm trying to create my own matrix math library for my game engine rather than using an existing one such as glm (a learning experience). I bit of code for reference:

template<size_t S1, size_t S2> struct matrix: std::array<std::array<float, S2>, S1>
{
    matrix()
    {
        *this = 0;
    }

    matrix<S1, S2>& operator=(const float& value)
    {
        for (uint32_t i = 0; i < S1; ++i)
        {
            for (uint32_t j = 0; j < S2; ++j)
            {
                this[i][j] = value;
            }
        }

        return *this;
    }

    // other operator overloads
};

struct vec2: matrix<1, 2>
{
    float& x()
    {
        return this->_M_elems[0][0];
    }

    float& y()
    {
        return this->_M_elems[0][1];
    }
};

struct vec3: matrix<1, 3>
{
    float& x()
    {
        return this->_M_elems[0][0];
    }
    float& y()
    {
        return this->_M_elems[0][1];
    }
    float& z()
    {
        return this->_M_elems[0][2];
    }
};

I'm trying to overload the multiplication operation (operator*) for my matrix struct so that when I try to multiple two matrices it performs the dot product of the two. A couple rules for performing the dot product on matrices are:

The number of columns of the 1st matrix must equal the number of rows of the 2nd matrix.

and

The result will have the same number of rows as the 1st matrix, and the same number of columns as the 2nd matrix.

And so I tried:

template<size_t S1, size_t S2> struct matrix: std::array<std::array<float, S2>, S1>
{
    matrix()
    {
        *this = 0;
    }

    matrix<S1, S2>& operator=(const float& value)
    {
        for (uint32_t i = 0; i < S1; ++i)
        {
            for (uint32_t j = 0; j < S2; ++j)
            {
                this[i][j] = value;
            }
        }

        return *this;
    }

    // other operator overloads

    matrix<S1, S3> operator*(const matrix<S2, S3>& multiplier)
    {
        matrix<S1, S3> dot_product;

        for (uint32_t i = 0; i < S1; ++i)
        {
            for (uint32_t j = 0; j < S2; ++j)
            {
                for (uint32_t k = 0; k < S3; ++k)
                {
                    dot_product[i][k] += (this[i][j] * multiplier[j][k]);
                }
            }
        }

        return dot_product;
    }
}

And I'm not even sure if that is the correct way to perform the dot product since it fails to compile with S3 not being defined anywhere. My question is, how should I pass as a function parameter matrix<S2, S3> where S2 is already defined within the struct and S3 is an unknown size?

Edit: Thanks to the generous help I was able to get my code to work, for a test case:

matrix<2, 3> test1;
matrix<3, 2> test2;

test1[0][0] = 1;
test1[0][1] = 2;
test1[0][2] = 3;
test1[1][0] = 4;
test1[1][1] = 5;
test1[1][2] = 6;
test2[0][0] = 6;
test2[0][1] = 5;
test2[1][0] = 4;
test2[1][1] = 3;
test2[2][0] = 2;
test2[2][1] = 1;

auto result = test1 * test2;

std::cout << test1 << std::endl;
std::cout << test2 << std::endl;
std::cout << result << std::endl;

prints to the console:

[ 1 2 3 ] 
[ 4 5 6 ]

[ 6 5 ] 
[ 4 3 ] 
[ 2 1 ]

[ 20 14 ] 
[ 56 41 ]

Which I verified here. I was only able to print the output to the console because of some other code not shown here (for posterity sake)

1 个答案:

答案 0 :(得分:2)

template<size_t S3>
matrix<S1, S3> operator*(const matrix<S2, S3>& multiplier)

Also your matrix<S1, S2>& operator=(const float& value) is wrong. The matrix corresponding to a float is generally a diagonal one.