[英]How can I mimic passing a std::pair as a template argument to a function in C++17?
[英]C++17 How to mimic Julia's 'promote_type' function using variadic template
由于某些个人原因,我正在研究 Julia 的SparseMatrixCSC
的 C++ 版本,该版本在我移植到 C++ 的项目中是特定的,而犰狳的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 blockdiag()
允许输入中的稀疏矩阵的可变参数数量和 output 中的一个“blockdiag”矩阵。 Julia 的脚本代码允许使用 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);
...
其中内部details::apply
function 允许递归地收集输入 n 矩阵上的行/列。 最终的矩阵维度在m
和n
中求和。 没问题,代码完美运行。
但是现在,我的问题是通过从类似typename
中收集/提升类型Tv
(值)和Ti
(索引)来计算输出矩阵的类型名参数。 由于稀疏矩阵的性质, Tv
和Ti
类型是数值。 更具体地说, Ti
是一个整数类型。
据我了解,因为我是使用最新标准 C++ 进行元编程的真正新手,所以最好的方法是使用<type_traits> std::common_type
。 但是我看不到如何解压缩我的可变参数模板 args(包含 SparseMatrixCSC)并使用获取一个或另一个内部列向量arma::Col<T>
的 decltype 的函子的结果扩展std::common_type<...>
参数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
function 中调用:
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
是 Julia 的 function 描述如下:
提升是指将混合类型的值转换为单一的通用类型。 当运算符(通常是数学)被赋予不同类型的 arguments 时,
promote_type
表示 Julia 中的默认提升行为。promote_type
类型通常会尝试返回一个类型,该类型至少可以近似任一输入类型的大多数值而不会过度扩展。 有些损失是可以容忍的; 例如,promote_type(Int64, Float64)
返回Float64
,尽管严格来说,并非所有Int64
值都可以完全表示为Float64
值。
由于每个args...
在这里:
template <typename... Args>
constexpr auto blockdiag(const Args& ...args)
本身就是一个SparseMatrixCSC
,让我们更明确地说:
template <typename... T, typename... U>
constexpr auto blockdiag(const SparseMatrixCSC<T, U>& ...args)
这blockdiag
的要求更容易理解(现在我们知道它需要什么),也更容易找出答案:我们在那里有T
和U
,所以只需使用 'em:
template <typename... T, typename... U>
constexpr auto blockdiag(const SparseMatrixCSC<T, U>& ...args)
-> SpareMatrixCSC<std::common_type_t<T...>, std::common_type_t<U...>>;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.