ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
14 июля
797848 Топик полностью
Ксения (28.11.2017 14:49 - 14:53, просмотров: 729) ответил Evgeny_CD на Спасибо! Классно пояснили!
Я вообще-то свой метод открыла :), как обойти явную типизацию, хотя и не уверена, что кто-то не открыл его раньше: Пример - имеем две квадратных матрицы, размером 128x128, с элементами типа double: Matrix M1(128,128), M2(128,128); // где Matrix - класс, аллокирующий им место в динамической памяти Здесь без динамической памяти не обойтись, т.к. матрицы бывают очень большими, а их размер - переменной величиной, в момент компиляции неизвестной. Из этих двух матриц можно получить целых 4 разных продукта их перемножения, в зависимости от их взаимной ориентации: M = M1 * M2; M = M1 * transpose(M2); M = transpose(M1) * M2; M = transpose(M1) * transpose(M2); Рассмотрим последний случай, как, казалось бы, наиболее сложный - в нем сразу две матрицы приходится транспонировать. Если делать это в лоб, то transpose() окажется функцией, которая будет вынуждена динамически проаллокировать новую матрицу транспонированного размера (т.е. по сути создать еще один объект типа Matrix), а потом скопировать туда данные из исходной матрицы "наперекосяк". Это накладно, т.к. транспонировать на том же месте в общем случае нельзя - исходная матрица может оказаться прямоугольной, не говоря уже о том, что портить аргумент нежелательно. А теперь оцените изящество моего решения :). У меня transpose() не функция, а преобразование типа (!) Matrix в тип TransposeMatrix. Такое преобразование типов возможно ВСЕГДА, т.к. оба класса совершенно одинаково определены, а в данном случае и подавно, т.к. TransposeMatrix является для класса Matrix базовым (формальное определение, т.к. ничем от своего базового он не отличается - просто так создать класс-копию проще всего). Никого лишнего кода при этом компилятор не генерирует: transpose(M2) выдает тот же адрес, что M2, но формально тип у этого адреса для самого компилятора сменился - стал TransposeMatrix вместо Matrix. А дальше совсем просто - есть 4 функции Multiply(), различающихся типом параметров: Multiply( &Mattix, &Mattix) Multiply( &Mattix, &TransposeMattix) Multiply( &TransposeMattix, &Mattix) Multiply( &TransposeMattix, &TransposeMattix) Каждая из которых выполняет умножение двух матриц, но у тех, где тип TransposeMattix индексы переставлены местами! Например, M2[j][i] вместо M2[i][j]. Т.е. транспонирование производится не явно, а путем перестановки индексов. Не трудно догадаться, что все 4 функции Multiply() написаны у меня на ассемблере с использованием AVX-инструкций :). При этом C++ код, включающий неявную типизацию, ничего лишнего не добавляет, а сводится к прямому вызову нужного варианта ассеблерной функции Multiply().