gpt4 book ai didi

C++ Vector Template Per-Component 操作

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:22:03 26 4
gpt4 key购买 nike

我正在重写项目的 vector 数学部分,我想根据 vector 的类型和维数来概括 vector 。 vector<T, N>表示类型为 T 的 N 维 vector 。

template<typename T, int N>
struct vector {
T data[N];
};

我需要重写许多 数学函数,其中大部分将在每个组件的基础上运行。加法运算符的直接实现如下所示。

template<typename T, int N>
vector<T, N> operator+(vector<T, N> lhs, vector<T, N> rhs) {
vector<T, N> result;
for (int i = 0; i < N; i++) {
result[i] = lhs[i] + rhs[i];
}
return result;
}

我的问题:有没有办法(通过模板技巧?)在不使用 for 的情况下实现它循环和一个临时变量?我知道编译器很可能会展开循环并将其优化掉。我只是不喜欢以这种方式实现所有对性能至关重要的数学函数的想法。它们都将被内联并包含在 header 中,因此拥有许多这些函数也会产生一个丑陋的大 header 文件。

我想知道是否有一种方法可以生成更优化的源代码。可能是一种像可变参数模板那样工作的方式。与此类似的东西。

template<typename T, int N>
vector<T, N> operator+(vector<T, N> lhs, vector<T, N> rhs) {
return vector<T, N>(lhs[0] + rhs[0], lhs[1] + rhs[1]...);
}

最佳答案

一种方法是通过较低级别的“ map ”功能:

这是一个完整的工作示例

#include <iostream>
#include <math.h>

template<typename T, int N>
struct vector {
T data[N];
};

首先声明您的工作人员“ map ”功能 - 我这里有 3 个 map , map2 , foreach .

template<typename T, int N, typename FN>
static void foreach(const vector<T,N> & vec, FN f) {
for(int i=0; i<N ;++i) {
f(vec.data[i]);
}
}

template<typename T, int N, typename FN>
static auto map(const vector<T,N> & vec, FN f) -> vector<decltype(f(T(0))), N> {
vector<decltype(f(T(0))), N> result;
for(int i=0; i<N ;++i) {
result.data[i] = f(vec.data[i]);
}
return result;
}

template<typename T1, typename T2, int N, typename FN>
static auto map2(const vector<T1,N> & vecA,
const vector<T2,N> & vecB,
FN f)
-> vector<decltype(f(T1(0), T2(0))), N> {
vector<decltype(f(T1(0), T2(0))), N> result;
for(int i=0; i<N ;++i) {
result.data[i] = f(vecA.data[i], vecB.data[i]);
}
return result;
}

现在使用帮助程序通过 lambda 定义更高级别的函数。我将定义二进制 +、二进制 -、一元 - 和 e^x .哦还有operator<<这样我们就可以看到发生了什么。

我很确定有更好的替代方案来替代 operator+ 中使用的 lambda 表达式和 operator- , 但我不记得了

template<typename T, int N>
vector<T,N> operator+(const vector<T,N> &lhs, const vector<T,N> &rhs) {
return map2(lhs, rhs, [](T a,T b) { return a+b;} );
}

template<typename T, int N>
vector<T,N> operator-(const vector<T,N> &lhs, const vector<T,N> &rhs) {
return map2(lhs, rhs, [](T a,T b) { return a-b;} );
}

template<typename T, int N>
vector<T,N> operator-(const vector<T,N> &vec) {
return map(vec, [](T a) { return -a;} );
}

template<typename T, int N>
auto exp(const vector<T,N> &vec) -> vector<decltype(exp(T(0))), N> {
return map(vec, [](T a) { return exp(a); } );
}

template<typename T, int N>
std::ostream & operator<<(std::ostream& os, const vector<T,N> &vec) {
os<<"{";
foreach(vec, [&os](T v) { os<<v<<", "; } );
os<<"}";
return os;
}

现在看看它们是如何工作的......

int main() {
vector<int, 5> v1 = {1,2,3,4,5};
vector<int, 5> v2 = {2,4,6,8,10};

std::cout<<v1 << " + " << v2 << " = " << v1+v2<<std::endl;
std::cout<<v1 << " - " << v2 << " = " << v1-v2<<std::endl;
std::cout<<" exp( - " << v2 << " )= " << exp(-v1)<<std::endl;
}

关于C++ Vector Template Per-Component 操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36026739/

26 4 0