По некоторым личным причинам я работал над C ++ версией Julia's SparseMatrixCSC
, которая задает c в проекте, который я портирую на C ++ и где Armadillo SpMat
не может быть идеальной альтернативой.
template <typename Tv, typename Ti>
struct SparseMatrixCSC
{
size_t m, n;
arma::Col<Ti> colptr;
arma::Col<Ti> rowval;
arma::Col<Tv> nzval;
};
Некоторые функции Julia, такие как blockdiag()
, допускают использование вариабельного c -образного числа разреженной матрицы на входе и одной матрицы 'blockdiag' на выходе. Скриптовый код Джулии допускает некоторый обобщенный метод c, который можно легко перенести с помощью C ++ 17, например, сбор размера n-матрицы во входных данных, например:
template <typename... Args>
constexpr auto blockdiag(const Args& ...args)
{
auto mX = details::apply([](auto x) { return size(x, 1); }, args...);
auto nX = details::apply([](auto x) { return size(x, 2); }, args...);
auto m = sum(mX);
auto n = sum(nX);
...
Где внутренний * Функция 1010 * позволяет рекурсивно собирать строки / столбцы на входной n-матрице. Окончательный размер матрицы суммируется в m
и n
. Нет проблем, код работает отлично.
Но теперь моя проблема состоит в том, чтобы вычислить typename
параметры матрицы вывода, собирая / продвигая типы Tv
(значение) и Ti
(индексирование) от чего-то похожего. По характеру матрицы разреженности типы Tv
и Ti
являются числовыми значениями. И, более конкретно, Ti
является целочисленным типом.
Как я понимаю, поскольку я настоящий новичок ie в метапрограммировании с последними стандартами C ++, лучший способ сделать это - использовать <type_traits> std::common_type
. Но я не вижу, как распаковать мои шаблонные аргументы c variadi (которые содержат SparseMatrixCS C) и развернуть параметры std::common_type<...>
с результатом функтора, который получает decltype того или иного внутреннего вектора столбца arma::Col<T>
. Что-то вроде:
template <typename Func, typename ... Args>
constexpr auto promote_type(Func f, Args const&... args)
{
return typename std::common_type<(f(args), ...)>::type;
}
Вызывается в предыдущей функции blockdiag
с помощью:
typename Tv = details::promote_type([](auto x) { return decltype(x.nzval); }, args...);
typename Ti = details::promote_type([](auto x) { return decltype(x.rowval); }, args...);
К сожалению, слишком плохо для компилятора VS2019 16.5.4
. Более того, я почти уверен, что выражение сгиба (f(args), ...)
недопустимо и не может использоваться в качестве параметра шаблона.
Итак, мне нужна ваша помощь, и я очень благодарен вам за это.
РЕДАКТИРОВАТЬ: Чтобы ответить Барри, promote_type
- это функция Джулии, описанная так:
Повышение означает преобразование значений смешанных типов в один общий тип. promote_type
представляет поведение продвижения по умолчанию в Julia, когда операторам (обычно математическим) задаются аргументы разных типов. promote_type
обычно пытается вернуть тип, который может по крайней мере приблизиться к большинству значений любого типа ввода без чрезмерного расширения. Некоторая потеря терпима; например, promote_type(Int64, Float64)
возвращает Float64
, хотя строго, не все Int64
значения могут быть представлены в точности как Float64
значения.