Я пытаюсь написать общий класс для симметричной блочной матрицы произвольной размерности. Дана только верхняя треугольная часть:
A B C
D E
F
поэтому количество блоков равно n*(n+1)/2, где n — размерность (здесь 3).
Возможная реализация с вариационными шаблонами (для простоты я использовал целые числа для блоков):
#include <tuple>
#include <cstddef>
template <size_t Dimension, typename... Blocks>
class SymmetricBlockMatrix {
public:
constexpr SymmetricBlockMatrix(Blocks... blocks): blocks(blocks...) { }
constexpr size_t dimension() const {
return Dimension;
}
protected:
const std::tuple<Blocks...> blocks;
};
int main() {
constexpr SymmetricBlockMatrix<3, int, int, int, int, int, int> m(1, 2, 3, 4, 5, 6);
return 0;
}
Я бы, конечно, проверил, соответствует ли количество блоков размеру.
Можно ли как-то явно указать только размерность и позволить компилятору определить типы блоков? Тогда я мог бы написать:
int main() {
constexpr SymmetricBlockMatrix<3> m(1, 2, 3, 4, 5, 6);
return 0;
}
Это приводит к следующей ошибке компилятора:
error: no matching function for call to 'SymmetricBlockMatrix<3>::SymmetricBlockMatrix(int, int, int, int, int, int)'
18 | constexpr SymmetricBlockMatrix<3> m(1, 2, 3, 4, 5, 6);
CTAD позволяет писать SymmetricBlockMatrix m(1, 2, 3, 4, 5, 6)
, но я не уверен, что это то, что вам нужно, без явного указания N
.
Имеет смысл, спасибо! Я написал другую версию кода, в которой размерность не указывается, а вычисляется на основе количества блоков.
Используйте старый вспомогательный метод make
и используйте auto
Могут ли типы отличаться друг от друга?
Кстати, вы можете использовать полный CTAD (вообще не указывать 3) с некоторой математикой.
Действительно! Но я думаю, что хорошо иметь эту информацию в явном виде. Да, блоки могут быть разных типов. В итоге я реализовал класс со вспомогательной функцией, которая работает как шарм.
Одним из обходных путей является использование старого трюка с шаблоном вспомогательной функции make
вместе с auto
, как показано ниже:
//this is a helper
template <size_t V, typename... T>
constexpr SymmetricBlockMatrix<V, T...> make_SymmetricBlockMatrix(T... t)
{
return SymmetricBlockMatrix<V, T...>{t...};
}
int main() {
constexpr SymmetricBlockMatrix<3, int, int, int, int, int, int> k(1, 2, 3, 4, 5, 6);
constexpr auto m = make_SymmetricBlockMatrix<3>(1, 2, 3, 4, 5, 6); //works now
}
О, это гениально, спасибо! Я как бы интуитивно почувствовал, что частичный вывод аргументов шаблона возможен (привет std::make_unique), теперь я понимаю, что это возможно для функций, а не классов.
Частичный синтаксис, подобный CTAD, не допускается.