30-03-2010, 22:35
|
|
|
חבר מתאריך: 30.07.05
הודעות: 949
|
|
למעשה שניכם טעיתם מעט בהבנת הכוונה שלי
א' - matrix הוא כן template...
ב' - אני בונה אופרטור שהוא template כפול - גם לפרמטר השמאלי וגם לימני... וכן, יש לזה משמעות עבורי...
הבעיה היא כשעושים כפל מטריצה בסקלר, כך שהאופרטור עדין ימשיך לעבוד.
הבעיה העיקרית הייתה מימוש מנגנון דומה למה שדיברתי עליו פה.
ולכן ככל שהביטוי ארוך יותר, אני אזדקק ליותר טיפוסים - לבנות משהו לא template-י לא יספיק לי...
בכל מקרה, די הסתדרתי עם מה שענו לי בתפוז... למרות שזה היה כרוך בדי הרבה דם יזע וקללות (לא בכיתי, בכ"ז...)
היה אתגר מעניין... גם אם לדבג template-ים זה סיוט...
למען הדורות הבאים, זה נראה כך:
PrimitiveBoxing.hpp
קוד PHP:
#pragma once
/* This document creates an AutoBoxing mechanism for primitives. * The boxing includes a degenerated indexing operator. * Composite elements are also boxed, but their functionality isn't hurt. */
// Helper type - Allows setting primitive types template <typename T> struct IsPrimitive { enum { VALUE = 0 }; };
#define SET_AS_PRIMITIVE(TYPE) template<> struct IsPrimitive<TYPE> { enum { VALUE = 1 }; }
// Pre-defined primitive types. If you require more types here - add them the same way. SET_AS_PRIMITIVE(char); SET_AS_PRIMITIVE(unsigned char); SET_AS_PRIMITIVE(short); SET_AS_PRIMITIVE(unsigned short); SET_AS_PRIMITIVE(int); SET_AS_PRIMITIVE(unsigned int); SET_AS_PRIMITIVE(long); SET_AS_PRIMITIVE(unsigned long); SET_AS_PRIMITIVE(__int64); SET_AS_PRIMITIVE(unsigned __int64); SET_AS_PRIMITIVE(float); SET_AS_PRIMITIVE(double); SET_AS_PRIMITIVE(long double);
// The boxing implementation: // Base class - if object is primitive - return it for each [] call. template <typename T, bool IS_PRIMITIVE> class IndexedBoxBase { public: typedef T Allocator; public: IndexedBoxBase(const T& src) : item(src) { } const T& operator[] (size_t index) const { return item; } bool IsPrimitive() const { return true; } protected: const T& item; };
// Base class - if object isn't primitive - return the true result of [] template <typename T> class IndexedBoxBase<T, false> { public: typedef T Allocator; public: IndexedBoxBase(const T& src) : item(src) { } const typename T::Allocator operator[] (size_t index) const { return item[index]; } bool IsPrimitive() const { return false; } const std::vector<size_t>& GetSize() const { return item.GetSize(); } const size_t& GetTotalSize() const { return item.GetTotalSize(); } protected: const T& item; };
// Determine which object is received and do as required. template <typename T> class IndexedBox : public IndexedBoxBase<T, IsPrimitive<T>::VALUE > { public: IndexedBox(const T& src) : IndexedBoxBase(src) { } };
Expression_Booster.hpp
קוד PHP:
#pragma once
#include "PrimitivesBoxing.hpp"
/* This document reduces costs for composite types mathematical expressions. * It is expected that a composite object will have an indexing [] operator. * This is done with some Meta-Programming - handle with care! */
/* ************************************************** ************************ */ /* ***** Representing classes ***** */ /* ************************************************** ************************ */
#define REPRESENTING_CLASS(name, operation) \ template <typename LEFT, typename RIGHT, bool LEFT_PRIMITIVE> \ class name \ { \ public: \ typedef typename LEFT::Allocator Allocator; \ public: \ name (const LEFT& l, const RIGHT& r) : left(l), right(r) { } \ name (const name &s) : left(s.left), right(s.right) { } \ const Allocator operator[] (size_t index) const \ { return (left[index]) operation (right[index]); } \ const std::vector<size_t>& GetSize() const { return left.GetSize(); } \ const size_t& GetTotalSize() const { return left.GetTotalSize(); } \ private: \ const IndexedBox<LEFT> left; \ const IndexedBox<RIGHT> right; \ }; \ template <typename LEFT, typename RIGHT> \ class name <LEFT, RIGHT, true> \ { \ public: \ typedef typename RIGHT::Allocator Allocator; \ public: \ name (const LEFT& l, const RIGHT& r) : left(l), right(r) { } \ name (const name &s) : left(s.left), right(s.right) { } \ const Allocator operator[] (size_t index) const \ { return (left[index]) operation (right[index]); } \ const std::vector<size_t>& GetSize() const { return right.GetSize(); } \ const size_t& GetTotalSize() const { return right.GetTotalSize(); } \ private: \ const IndexedBox<LEFT> left; \ const IndexedBox<RIGHT> right; \ }
REPRESENTING_CLASS(composite_add, +); REPRESENTING_CLASS(composite_sub, -); REPRESENTING_CLASS(composite_mul, *); REPRESENTING_CLASS(composite_div, /);
/* ************************************************** ************************ */ /* ***** Required operators ***** */ /* ************************************************** ************************ */
#define COMPOSITE_TYPE_OPERATOR(operation, class_name) \ template <typename LEFT, typename RIGHT> \ class_name <LEFT, RIGHT, IsPrimitive<LEFT>::VALUE> operator operation \ (const LEFT &l, const RIGHT &r) \ { \ return class_name <LEFT, RIGHT, IsPrimitive<LEFT>::VALUE>(l, r); \ } \ COMPOSITE_TYPE_OPERATOR(+, composite_add) COMPOSITE_TYPE_OPERATOR(-, composite_sub) COMPOSITE_TYPE_OPERATOR(*, composite_mul) COMPOSITE_TYPE_OPERATOR(/, composite_div)
מה שמאפשר לביטויים כמו
קוד:
C = (2.0*A + B * 3.0)*2 + A*B;
לרוץ ולעבוד אפילו כאשר המטריצות מוגדרות כ
קוד:
Matrix<Matrix<double> > A
_____________________________________
חתימתכם הוסרה כיוון שלא עמדה בחוקי האתר. לפרטים נוספים לחצו כאן. תוכלו לקבל עזרה להתאמת החתימה לחוקים בפורום חתימות וצלמיות.
נערך לאחרונה ע"י Dark Knight בתאריך 30-03-2010 בשעה 22:45.
|