c++ - 模板元编程特征表达式
问题描述
假设我有一些(短)向量,我在编译时知道它的长度,还有另一个更长的向量,我在编译时不知道它的长度。我可以写这样的东西:
template<int N>
Eigen::ArrayXd do_transformation(Eigen::Array<double,N,1> short_vec, Eigen::ArrayXd long_vec){
Eigen::ArrayXd return_vector(long_vec.size());
for(int i=0; i<N; i++){
return_vector+=short_vec(i)*long_vec.pow(2-i);
}
return return_vector;
}
有没有一种方法可以使用表达式模板构造该总和而无需写出:
template<>
Eigen::ArrayXd do_transformation<1>(Eigen::Array<double,1,1> short_vec, Eigen::ArrayXd long_vec){
return short_vec(0)*long_vec.pow(2);
}
template<>
Eigen::ArrayXd do_transformation<2>(Eigen::Array<double,2,1> short_vec, Eigen::ArrayXd long_vec){
return short_vec(0)*long_vec.pow(2)+short_vec(1)*long_vec.pow(1);
}
对于每个 N 值?
理想情况下,这可以在c++11
. 真正令人敬畏的是函数返回某种特征表达式,这样我就可以执行以下操作:
long_vec+do_transformation(short_vec,long_vec)
并让 Eigen 指示编译器生成只遍历向量一次的代码。
解决方案
如果您可以使用 C++17,我想您可以使用辅助函数(dth()
在下面的示例中),std::make_index_sequence
/std::index_sequence
和模板折叠。
如下所示(注意:代码未测试):
template <int N, std::size_t ... Is>
Eigen::ArrayXd dth (Eigen::Array<double,N,1> short_vec,
Eigen::ArrayXd long_vec,
std::index_sequence<Is...>)
{ return ((short_vec(Is) * long_vec.pow(2-Is)) + ...); }
template <int N>
Eigen::ArrayXd do_transformation (Eigen::Array<double,N,1> short_vec,
Eigen::ArrayXd long_vec)
{ return dth(short_vec, long_vec, std::make_index_sequence<N>{}); }
如果你不能使用 C++17,但是你可以使用 C++14,那么辅助函数会变得有点复杂(如果你愿意,我可以写一个例子),因为你不能使用模板折叠。
template <int N, std::size_t ... Is>
Eigen::ArrayXd dth (Eigen::Array<double,N,1> short_vec,
Eigen::ArrayXd long_vec,
std::index_sequence<Is...>)
{
using unused = int[];
Eigen::ArrayXd rv(long_vec.size());
(void)unused { 0, (rv += short_vec(Is) * long_vec.pow(2-Is), 0)... };
return rv;
}
对于 C++11 解决方案,您需要为std::index_sequence
/创建一个替换std::make_index_sequence
。
推荐阅读
- mysql - 如何将主键添加到 mysql 表作为第一列
- azure - 如何连接 Microsoft Azure Active Directory
- java - Jconsole 远程连接丢失:重新连接?
- laravel - 取 %string% 和 %tring% 时的区别
- d3.js - 折线图中显示的日期不正确的问题
- java - 在 cmd javac -version 上获取“不兼容的魔法值 0”
- apache-kafka - 使用 SQL Server 上的 JDBC Sink 连接器自动创建适当的 DATETIME 类型字段
- javascript - 动画元素到鼠标光标
- javascript - 无法读取用于发送短信的表单中未定义的属性“setState”
- c# - 没有注册类型 T 的服务 WebApi 3.1