template<int N>
class Tuple {
public:
Tuple operator+(const Tuple& rhs) const
{
Tuple result;
for(int i=0; i<N; ++i)
result.data[i] = data[i] + rhs.data[i];
return result;
}
float data[N];
};
class Vec3 : public Tuple<3> {
public:
Vec3(float x, float y, float z) {
data[0] = x; data[1] = y; data[2] = z;
}
};
int main() {
Vec3 v1(1, 2, 3);
Vec3 v2(4, 5, 6);
// Compilation error: v1 + v2 is returning Tuple but not Vec3
Vec3 v3 = v1 + v2;
return 0;
}
大家不用擔心那個回圈會為性能帶來負面影響,編譯器懂得把它優化 (我已在VC2008上證實了這一點)。
但由於運算子的返回型態出了問題,我們作出以下嘗試:
template<int N, class R>
class Tuple {
public:
R operator+(const Tuple& rhs) const
{
R result;
for(int i=0; i<N; ++i)
result.data[i] = data[i] + rhs.data[i];
return result;
}
float data[N];
};
class Vec3 : public Tuple<3, Vec3> {
public:
Vec3(float x, float y, float z) {
data[0] = x; data[1] = y; data[2] = z;
}
};
int main() {
Vec3 v1(1, 2, 3);
Vec3 v2(4, 5, 6);
Vec3 v3 = v1 + v2;
return 0;
}
非常好。不過還可以更好哩:
template<int N, class R, class U>
class Tuple : public U {
public:
R operator+(const Tuple& rhs) const
{
R result;
for(int i=0; i<N; ++i)
result.data[i] = data[i] + rhs.data[i];
return result;
}
};
struct _Vec3Union {
union {
struct { float x, y, z; };
float data[3];
};
};
class Vec3 : public Tuple<3, Vec3, _Vec3Union> {
public:
Vec3() {}
Vec3(float x_, float y_, float z_) {
x = x_; y = y_; z = z_;
}
};
struct _SizeUnion {
union {
struct { float width, height; };
float data[2];
};
};
class Size : public Tuple<2, Size, _SizeUnion> {
public:
Size() {}
Size(float w, float h) {
width = w; height = h;
}
};
int main() {
Vec3 v1(1, 2, 3);
Vec3 v2(4, 5, 6);
Vec3 v3 = v1 + v2;
Size s1(1, 2);
Size s2(2, 3);
Size s3 = s1 + s2;
return 0;
}
這可讓 Vec3 組成的 x, y 和 z 用方便的形式去存取。
儘管以上的提示未必有多大用途,還望它能加強大家對 C++ 的了解。
1. 會有padding 的問題嗎??
回覆刪除2. 可以應用於 SIMD 嗎 ??
1. 用家需要於 _XXXUnion 裡自行解決Padding 的問題.
回覆刪除2. 不太可行. 你可以把 __m128 混入 _XXXUnion 裡, 但基類別 Tuple 須要處理不同長度的結構. 你可以在 Vec4 裡加入特化來達到效果, 但這就不是我想強調的共享罷了.
Vector, Point 和其他型別所需要的 operators 都不一樣. 例如 Vector 有 Add, Subtract, Dot. Point 應該只有 Subtract, 而 Subtract 的 return type 是 Vector.
回覆刪除要做到這樣是不是可以...
template<int N, T> class Vector<N, T> :
public Add<N, Vector<N, T> >,
public Subtract<N, Vector<N, T> >,
public Dot<N, T>
{
}
但這樣好像不能實現, 因為 data 只應該有一份.
Template Meta Programming... 還是簡單些好?
唔...有道理. 也許只能用於 Vector 和 Matrix, 非常有限.
回覆刪除所以最後我說了一句: "儘管以上的提示未必有多大用途,還望它能加強大家對 C++ 的了解." :)