Wat vinden jullie hier eigenlijk van? Heeft het tegenwoordig nog nut, of is het iets dat je beter niet kan doen om de leesbaarheid/aanpasbaarheid voor anderen te bevorderen?
Voor de grap zat ik even een template meta vector te maken; meer als oefening om het niet weg te laten zakken. Maar kwam dus op het volgende:
Nou blijkt dat voor de template code, en de commented runtime loops uiteindelijk exact dezelfde code wordt gegenereerd. Voor beiden voor de dot product nl.
Toen begon ik me ineens af te vragen waarom je tegenwoordig nog dit soort dingen zou gebruiken. Als een compiler nieuw/goed genoeg is om al die template code correct te compilen, dan is deze ook wel slim genoeg om zelf te optimizen. Eigenlijk neem je met meta programs het heft in eigen hand, en vertel je de compiler exact wat te doen. Maar ik denk dat compilers tegenwoordig het zelf veel beter kunnen.
Vroeg me af hoe hier over gedacht wordt...het blijft natuurlijk een leuke denk oefening
Voor de grap zat ik even een template meta vector te maken; meer als oefening om het niet weg te laten zakken. Maar kwam dus op het volgende:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
| #define CompileTimeAssert(expr, msg) typedef char ERROR_##msg##[1][(expr)] template <int N, typename ScalarT> struct DotProduct { static ScalarT result(const ScalarT* lhs, const ScalarT* rhs) { return *lhs * *rhs + DotProduct<N-1, ScalarT>::result(lhs+1, rhs+1); } }; template <typename ScalarT> struct DotProduct<1, ScalarT> { static ScalarT result(const ScalarT* lhs, const ScalarT* rhs) { return *lhs * *rhs; } }; template <typename DestT, typename SrcT> struct SumOperation { static void perform(DestT* dst, SrcT* src) {*dst += *src;} }; template <int N, typename ScalarT, template <typename T1, typename T2> class Operation> struct OperateSelf { static void result(ScalarT* dst, const ScalarT* src) { Operation<ScalarT, const ScalarT>::perform(dst, src); OperateSelf<N-1, ScalarT, Operation>::result(dst+1, src+1); } }; template <typename ScalarT, template <typename T1, typename T2> class Operation> struct OperateSelf<0, ScalarT, Operation> { static void result(ScalarT* dst, const ScalarT* src) {} }; template < typename ScalarT, int Dim > class Vector { public: Vector() {} ~Vector() {} ScalarT operator%(const Vector<ScalarT, Dim>& rhs) const { return DotProduct<Dim, ScalarT>::result(data_, rhs.data_); // float result = 0; // for (int i=0; i<Dim; ++i) { // result += data_[i] * rhs.data_[i]; // } // return result; } Vector<ScalarT, Dim>& operator+=(const Vector<ScalarT, Dim>& rhs) { OperateSelf<Dim, ScalarT, SumOperation>::result(data_, rhs.data_); // for (int i=0; i<Dim; ++i) { // data_[i] += rhs.data_[i]; // } return *this; } ScalarT& operator[](unsigned int i) { return data_[i]; } const ScalarT& operator[](unsigned int i) const { return data_[i]; } template <int Index> void set(ScalarT value) { CompileTimeAssert(Index < Dim, Vector_Index_out_of_range); data_[Index] = value; } template <int Index> ScalarT get() const { CompileTimeAssert(Index < Dim, Vector_Index_out_of_range); return data_[Index]; } private: ScalarT data_[Dim]; }; |
Nou blijkt dat voor de template code, en de commented runtime loops uiteindelijk exact dezelfde code wordt gegenereerd. Voor beiden voor de dot product nl.
GAS:
1
2
3
4
5
6
7
8
9
10
11
| ; 18 : float a = v1 % v2; fld DWORD PTR _v2$[esp+40] fmul DWORD PTR _v1$[esp+40] fld DWORD PTR _v2$[esp+36] fmul DWORD PTR _v1$[esp+36] faddp ST(1), ST(0) fld DWORD PTR _v2$[esp+32] fmul DWORD PTR _v1$[esp+32] faddp ST(1), ST(0) fstp DWORD PTR _a$[esp+32] |
Toen begon ik me ineens af te vragen waarom je tegenwoordig nog dit soort dingen zou gebruiken. Als een compiler nieuw/goed genoeg is om al die template code correct te compilen, dan is deze ook wel slim genoeg om zelf te optimizen. Eigenlijk neem je met meta programs het heft in eigen hand, en vertel je de compiler exact wat te doen. Maar ik denk dat compilers tegenwoordig het zelf veel beter kunnen.
Vroeg me af hoe hier over gedacht wordt...het blijft natuurlijk een leuke denk oefening
[ Voor 5% gewijzigd door Zoijar op 09-10-2004 13:56 ]