Как указать произвольный аргумент шаблона для параметра функции?

#c #templates

#c #шаблоны

Вопрос:

Я не был уверен, как сформулировать то, что я спрашиваю, поэтому, надеюсь, какой-нибудь код прояснит это. Я пытаюсь создать свою собственную матричную математическую библиотеку для своего игрового движка, а не использовать существующую, такую как glm (a learning experience). I бит кода для справки:

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

    matrix<S1, S2>amp; operator=(const floatamp; 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>
{
    floatamp; x()
    {
        return this->_M_elems[0][0];
    }

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

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

Я пытаюсь перегрузить операцию умножения ( operator* ) для моей матричной структуры, чтобы при попытке использовать несколько двух матриц она выполняла скалярное произведение двух. Пара правил для выполнения скалярного произведения на матрицах:

Количество столбцов 1-й матрицы должно равняться количеству строк 2-й матрицы.

и

Результат будет иметь то же количество строк, что и 1-я матрица, и то же количество столбцов, что и 2-я матрица.

И поэтому я попытался:

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

    matrix<S1, S2>amp; operator=(const floatamp; 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>amp; 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;
    }
}
 

И я даже не уверен, что это правильный способ выполнения точечного произведения, поскольку он не может скомпилироваться, поскольку S3 нигде не определен. Мой вопрос в том, как я должен передать в качестве параметра функции matrix<S2, S3> , где S2 уже определен в структуре, а S3 — неизвестный размер?

Редактировать: Благодаря щедрой помощи я смог заставить свой код работать для тестового примера:

 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;
 

выводит на консоль:

 [ 1 2 3 ] 
[ 4 5 6 ]

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

[ 20 14 ] 
[ 56 41 ]
 

Что я проверил здесь .Я смог распечатать вывод на консоль только из-за какого-то другого кода, не показанного здесь (для потомков)

Комментарии:

1. @Amadeus извиняется, это именно то, что произошло, когда я вставил из своей ide

2. вы также должны сделать operator* шаблонной функцией, например: template <size_t S3> matrix<S1, S3> operator*(const matrix<S2,S3>amp; multiplier)...

3. @linuxfever Клянусь, я мог бы поклясться, что пробовал это, и это выдало ошибку компилятора, но теперь это определенно работает, спасибо.

Ответ №1:

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

Также ваш matrix<S1, S2>amp; operator=(const floatamp; value) неверен. Матрица, соответствующая переменной с плавающей точкой, обычно является диагональной.

Комментарии:

1. Ради потомства не могли бы вы изменить class S3 на size_t S3 > И, кстати, спасибо

2. не уверен, что означает ваш комментарий? мой код работает так, как задумано, см. Мою правку

3. а, теперь я понимаю, что вы имеете в виду. Да, это неверно, но я даже не думал об этом, я только объединил эту перегрузку, чтобы я мог обнулить матрицу при создании, но спасибо, что указали на это.