לוגו אתר Fresh          
 
 
  אפשרות תפריט  ראשי     אפשרות תפריט  צ'אט     אפשרות תפריט  מבזקים     אפשרות תפריט  צור קשר     חץ שמאלה ‎print ‎"Hello World!"; if‎ ‎not rules.‎know ‎then rules.‎read(); חץ ימינה  

לך אחורה   לובי הפורומים > מחשבים > תכנות ובניית אתרים
שמור לעצמך קישור לדף זה באתרי שמירת קישורים חברתיים
תגובה
 
כלי אשכול חפש באשכול זה



  #1  
ישן 29-03-2010, 21:41
  Dark Knight Dark Knight אינו מחובר  
 
חבר מתאריך: 30.07.05
הודעות: 949
שלח הודעה דרך ICQ אל Dark Knight
++C -אפשר לעשות template לטיפוסים פרימיטיביים בלבד?

אפשר לעשות template לטיפוסים פרימיטיביים בלבד?
או מכיוון אחר - לטיפוסי מחלקה בלבד?

אם לא, אפשר לעשות סוג של autoBoxing ב-++C?

כעקרון, אני צריך שתהיה לי מחלקה כזו בערך:

קוד PHP:
 template  <typename T>
class 
PrimitiveBox
{
public:
    
PrimitiveBox(const Tsrc) : item(src) { }
    const 
T&  operator[] (size_t index) const { return item; }
    
Toperator[]  (size_t index) { return item; }
    
Toperator() () { return item; }
private:
    
Titem;
}; 



כאשר T הוא טיפוס פרימיטיבי בשפה - char, short, int, long ה-unsigned למניהם, float ו-double; לא מחלקה.

מנגד אני רוצה פונקציה שתתנהג בערך ככה:

קוד PHP:
 template  <class T>
int foo(const Tt)
{
    return 
t[10];



ומן הסתם לא תוכל לקבל פרימיטיבים שלהם אין אופרטור []...
אבל אני עדין רוצה כתיבה ברורה: cout << foo(10) << endl;
ושיתבצע Boxing אוטומטי של 10 ב-PrimitiveBox.

זו לא סתם גחמה, המטרה שלי היא שה-boxing יקרה עבור אופרטור מתמטי... להוסיף Boxing ידני בכל מקום יהפוך ביטויים מתמטיים לקריאים פחות: PrimitiveBox<int>(10)*MyMatrix נראה זוועה לעומת 10*MyMatrix...

בינתיים לא הצלחתי להביא למצב הזה בשום אופן... יש למישהו רעיונות בשבילי?

* במקרה הכי גרוע אני אכתוב את ה-templates הספציפיים ידנית ע"י ספציפיקציית templates אבל זה יהיה כמות נוראית של שורות כמעט זהות והייתי מעדיף להמנע...
הנקודה היא שהנוחיות בשימוש וקריאות המשוואות המתקבלות בשימוש הסופי חשובות פה במידה ניכרת מהנוחות של כתיבת הקוד של המחלקה עצמה (אחד המצבים בו ה-trade-off של נוחיות המנשק לנוחיות הפיתוח מוטה באופן כמעט מוחלט לכיוון נוחיות המנשק)
_____________________________________
חתימתכם הוסרה כיוון שלא עמדה בחוקי האתר. לפרטים נוספים לחצו כאן. תוכלו לקבל עזרה להתאמת החתימה לחוקים בפורום חתימות וצלמיות.

תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #4  
ישן 30-03-2010, 12:21
  cplusplus cplusplus אינו מחובר  
 
חבר מתאריך: 13.03.10
הודעות: 5
בתגובה להודעה מספר 1 שנכתבה על ידי Dark Knight שמתחילה ב "++C -אפשר לעשות template לטיפוסים פרימיטיביים בלבד?"

למרות שאני חושב שזה מטופש להמציא את הגלגל מחדש, אני אראה לך איך לממש את זה בעצמך:
קוד:
template<class T, class U> struct Typelist { typedef T Current; typedef U Next; }; struct NullType {}; template<class List, class T> struct Search; template<class Current, class Next, class T> struct Search<Typelist<Current, Next>, T> { enum { value = Search<Next, T>::value }; }; template<class T, class Next> struct Search<Typelist<T, Next>, T> { enum { value = true }; }; template<class T> struct Search<NullType, T> { enum { value = false }; }; typedef Typelist<char, Typelist<short, Typelist<int, Typelist<long, NullType> > > > primitives; template<bool Assert> struct StaticAssert; template<> struct StaticAssert<true> { enum { check = true }; }; template<class T, bool check = StaticAssert<Search<primitives, T>::value >::check> class PrimitivesOnly { }; int main() { PrimitivesOnly<int> x; // works! PrimitivesOnly<float> y; // doesn't work! 'check' : invalid template argument for 'PrimitivesOnly' class UserDefinedType { }; PrimitivesOnly<UserDefinedType> z; // doesn't work! }

הרעיון הוא שיש לך TYPELIST ובזמן קומפילציה אתה מטייל על הרשימה, אם הגעת לNODE שיש בו את הTYPE שאתה מחפש, אז תחזיר TRUE, אחרת FALSE.
לאחר מכן יש לך STATICASSERT שבודק אם תנאי כלשהו מתקיים בזמן קומפילציה.
אני חושב שזה די חזק.
המלצה חמה: תקרא את הספר Modern C++ , קראתי את רובו, בכלל TEMPLATE METAPROGRAMMING זה נושא שאפשר לעשות איתו הרבה מעבר למה שהראתי לך פה.

בהצלחה!
פונדי.
_____________________________________
There are only two kinds of languages: the ones people complain about and the ones nobody uses


נערך לאחרונה ע"י cplusplus בתאריך 30-03-2010 בשעה 12:24.
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #7  
ישן 30-03-2010, 22:28
צלמית המשתמש של פסטן
  פסטן פסטן אינו מחובר  
 
חבר מתאריך: 14.12.09
הודעות: 9,751
בתגובה להודעה מספר 6 שנכתבה על ידי cplusplus שמתחילה ב "פסטן, נראה לי שהוא התכוון..."

אני לא בטוח שצריך template בשביל דבר כזה. אני יותא מנקודת הנחה ש-Matrix היא
מחלקה רגילה (לא template), ובהמשך אסביר למה ואפרט מה קורה אם היא כן template.
במקרה הזה, צריך רק אופרטורים:
קוד:
Matrix operator*(const double& left, const Matrix& right); Matrix operator*(const Matrix& left, const double& right);

וכל טיפוס מספרי יעבור promotion ו/או cast אוטומטי ל-double. אפשר גם long double אם
זה מה שיש במימוש הפנימי של Matrix.

הסיבה שאני מניח ש-Matrix מבוססת על double או long double ולא טמפלייטית היא
שמטריצה איננה מבנה נתונים בסגנון רשימה, טבלה, tuple וכו' אלא אובייקט מתמטי שיש
לפעולות עליה (כפל בסקלר, כפל מטריצות) משמעות פשוטה רק אם מדברים על מספרים.

כמובן שיכול להיות שרוצים לעשות "מטריצות" של דברים אחרים, אבל הדברים האחרים
האלה יצטרכו להתנהג כמו מספרים (להגדיר אופרטורים בעלי משמעות כמו שיש למספרים),
ואז גם שווה לעשות להם implicit constructor מ-double ואופרטור cast ל-double.
לחילופין, אפשר באמת להשתמש ב-template במקרה הזה, אבל אז עדיין לא צריך לעשות
כלום, כי הקוד פשוט לא יתקמפל אם למחלקה שינסו לעשות מטריצה שלה לא יהיו האופרטורים
המתאימים.
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #8  
ישן 30-03-2010, 22:35
  Dark Knight Dark Knight אינו מחובר  
 
חבר מתאריך: 30.07.05
הודעות: 949
שלח הודעה דרך ICQ אל Dark Knight
בתגובה להודעה מספר 6 שנכתבה על ידי cplusplus שמתחילה ב "פסטן, נראה לי שהוא התכוון..."

למעשה שניכם טעיתם מעט בהבנת הכוונה שלי
א' - 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 };
};

#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 Tbool IS_PRIMITIVE>
class 
IndexedBoxBase
{
public:
    
typedef T Allocator;
public:
    
IndexedBoxBase(const Tsrc) : item(src) { }
    const 
Toperator[] (size_t index) const { return item; }
    
bool IsPrimitive() const { return true; }
protected:
    const 
Titem;
};

// Base class - if object isn't primitive - return the true result of []
template <typename T>
class 
IndexedBoxBase<Tfalse>
{
public:
    
typedef T Allocator;
public: 
    
IndexedBoxBase(const Tsrc) : 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_tGetTotalSize() const { return item.GetTotalSize(); }
protected:
    const 
Titem;
};

// Determine which object is received and do as required.
template <typename T>
class 
IndexedBox : public IndexedBoxBase<TIsPrimitive<T>::VALUE >
{
public:
    
IndexedBox(const Tsrc) : 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 LEFTtypename RIGHTbool LEFT_PRIMITIVE> \
class 
name \
{ \
public: \
    
typedef typename LEFT::Allocator Allocator; \
public: \
    
name (const LEFTl, const RIGHTr) : 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_tGetTotalSize() const { return left.GetTotalSize(); } \
private: \
    const 
IndexedBox<LEFTleft; \
    const 
IndexedBox<RIGHTright; \
}; \
template <typename LEFTtypename RIGHT> \
class 
name <LEFTRIGHTtrue> \
{ \
public: \
    
typedef typename RIGHT::Allocator Allocator; \
public: \
    
name (const LEFTl, const RIGHTr) : 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_tGetTotalSize() const { return right.GetTotalSize(); } \
private: \
    const 
IndexedBox<LEFTleft; \
    const 
IndexedBox<RIGHTright; \
}

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 LEFTtypename RIGHT> \
class_name <LEFTRIGHTIsPrimitive<LEFT>::VALUEoperator operation \
    (const 
LEFT &l, const RIGHT &r) \
{ \
    return 
class_name <LEFTRIGHTIsPrimitive<LEFT>::VALUE>(lr); \
} \
 
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.
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #10  
ישן 30-03-2010, 23:40
  Dark Knight Dark Knight אינו מחובר  
 
חבר מתאריך: 30.07.05
הודעות: 949
שלח הודעה דרך ICQ אל Dark Knight
בתגובה להודעה מספר 9 שנכתבה על ידי פסטן שמתחילה ב "יכול להיות שאני לא מבין משהו"

1. ההגיון הוא בידי המשתמש...
ישנם שימושים בתחומים באווירונאוטיקה שבהם יש דבר כזה שנקרא מטריצת בלוקים. ייצוג של מטריצה במטריציה נוח עבור זה.
2. כי כשיש לך ביטוי ארוך כמו זה שהצגתי - בסוגריים יווצר בסופו של דבר הטיפוס:
קוד:
composite_add<composite_mul< Matrix<Matrix<double>> ,Matrix<Matrix<double>>>, composite_mul< Matrix<Matrix<double>> ,Matrix<Matrix<double>>>>

שיהיה הקלט לאופרטור + מחוץ לסוגריים... מכיר דרך יותר מוצלחת מ-template לאכול את המפלצת הזו?

3. לא מבין איך זה "באג"... לא רואה מה לא בסדר בזה... תפרט אם תרצה תשובה מתאימה, ואם טעיתי בשם של התופעה ולא עשיתי "boxing" לפי הספר - אז לא נורא.. זו ההתנהגות שהייתי צריך.
4. ההגיון הוא שבפעולות המורכבות זה מאפשר לי לעבוד עם סקלרים בלי צורך בהתייחסות מיוחדת וזו ההתנהגות שהייתה חשובה לי...
5. תקבל שגיאת קומפילציה... פונקציות הגדולים היו סוג של אינוס שעשיתי אחרי די הרבה זמן של debug של הסיפור הזה אחרי שנסיונות אחרים עשו כל מני בעיות... לא יפה אבל בסופו של דבר בניתי את כל הסיפור הזה למטרה מאד ספציפית אז העדפתי בשלב מסיום לוותר על חלק מהגמישות לטובת סיום העבודה על זה.
אם צריך עוד פרימיטיבים, אפשר להוסיף לרשימה. אם לא מדובר בטיפוס מורכב - אין שום משמעות לכל מה שעשיתי שם ולכן שגיאת קומפילציה תהיה במקום...
פונקציות הגודל היו חשובות כאשר מנסים להשתמש בטיפוסי האופרטורים ע"מ ליצור מטריצה או השמה למטריצה ריקה.

אני מניח שצריך להבין את המטרות העיקריות של הבעיה כדי להבין את הפתרון שבחרתי...
הקוד הזה נוצר עבור חבר,יש בו מספר דברים מאד ספציפיים עבור אותו החבר...
אותו חבר שלי, לא ממש מתכנת ולא מכיר את ++C לעומק, הוא מממש מספר אלגוריתמים שקשורים בכלל באווירונאוטיקה.

הוא צריך מחלקה שתהיה מצד אחד יעילה מאד, ומצד שני אפשרות לכתוב משוואות וביטויים (מאד) ארוכים בצורה קריאה.

מהבחינה הזו פתרון של זמן-קומפילציה במקום יצירת עותקים הוא פתרון יעיל מאד עבור הפעולות המתמטיות, וכל המפלצת הזו נוצרה עבור קריאות של הקוד שיווצר א"כ... כדי שהוא יוכל לוודא שהעתיק את הנוסחאות והמשוואות שפיתח על הדף בצורה נכונה - זה משהו שאין לו תחליף עבורו (נראה אותך כותב משוואה של משהו כמו 10 פעולות כשבכל מקום צריך לדחוף שמות של טיפוסים ושות')
_____________________________________
חתימתכם הוסרה כיוון שלא עמדה בחוקי האתר. לפרטים נוספים לחצו כאן. תוכלו לקבל עזרה להתאמת החתימה לחוקים בפורום חתימות וצלמיות.

תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #12  
ישן 31-03-2010, 11:57
  Dark Knight Dark Knight אינו מחובר  
 
חבר מתאריך: 30.07.05
הודעות: 949
שלח הודעה דרך ICQ אל Dark Knight
בתגובה להודעה מספר 11 שנכתבה על ידי פסטן שמתחילה ב "[right]2. אופרטורי קאסט,..."

2. ירושה גוררת פולימורפיזם שזה כבר גורר virtual tables וזה כבר נפתר בזמן ריצה - דופק את כל האופטימיזציה... פה כל הביטוי יכול לעבור inlining... אתה מחייב קריאה ממש לפונקציה...
אופרטורי cast עדין צריכים להכתב וזה פוגע בכתיבה של הביטוי...

3. השימוש שלך שונה מהשימוש שלי - כל הביטויים שאני כותב חיים בזמן חישוב הביטוי בלבד. לכל אורך הזמן הזה גם איברים זמניים לא נמחקים.
אתה לא אמור, בשום נקודת זמן, לעשות explicit construction של אף אחת מהמחלקות שם... כל המטרה זה שהן יווצרו לבד רק בתוך האופרטורים ושתוחלת החיים שלהם תסתכם בביטוי יחיד. מהבחינה הזו, כשהכל מההתחלה ועד הסוף רץ על const reference - זה עושה את העבודה.
מה שכן, העלת נקודה מעניינת למצבים אחרים, בהחלט משהו לחשוב עליו באופן כללי.
_____________________________________
חתימתכם הוסרה כיוון שלא עמדה בחוקי האתר. לפרטים נוספים לחצו כאן. תוכלו לקבל עזרה להתאמת החתימה לחוקים בפורום חתימות וצלמיות.

תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
  #15  
ישן 31-03-2010, 13:23
צלמית המשתמש של פסטן
  פסטן פסטן אינו מחובר  
 
חבר מתאריך: 14.12.09
הודעות: 9,751
בתגובה להודעה מספר 14 שנכתבה על ידי Dark Knight שמתחילה ב "2. עבור templates אין דבר כזה..."

2. יכול להיות ששוב לא הבנתי למה אתה מתכוון:
קוד:
#include <iostream> template<typename T> class Num { public: typedef T NumericT; Num(const NumericT& d) : m_n(d) {} ~Num() {} operator double() { return m_n; } private: NumericT m_n; }; template<typename T> class Num2 { public: typedef T NumericT; Num2(const NumericT& d) : m_n(d) {} ~Num2() {} operator double() { return m_n; } template<typename U> operator Num<U>() { std::cout << "CASTING" << std::endl; return Num<U>(m_n); } private: NumericT m_n; }; int main() { Num<float> i(1.23f); std::cout << i << std::endl; Num2<int> j(123); Num<long> jj = j; std::cout << j << std::endl << jj << std::endl; Num2<double> k(12.34); Num<long> kk = k; std::cout << k << std::endl << kk << std::endl; return 0; }

אל תשכח שאם אתה ממיר לאותו טיפוס טמפלייטי, אופרטור הקאסט לא צריך להיות טמפלייטי, ואז נחסכות הבעיות במקרים האחרים.

3. זה גם הטיעון בעד לא להשתמש ב-const: "מי שמספיק טיפש לשנות את המשתנה גם אם ההערה מעליו אומרת לא לשנות - מגיע לו"...
תגובה ללא ציטוט תגובה עם ציטוט חזרה לפורום
תגובה

כלי אשכול חפש באשכול זה
חפש באשכול זה:

חיפוש מתקדם
מצבי תצוגה דרג אשכול זה
דרג אשכול זה:

מזער את תיבת המידע אפשרויות משלוח הודעות
אתה לא יכול לפתוח אשכולות חדשים
אתה לא יכול להגיב לאשכולות
אתה לא יכול לצרף קבצים
אתה לא יכול לערוך את ההודעות שלך

קוד vB פעיל
קוד [IMG] פעיל
קוד HTML כבוי
מעבר לפורום



כל הזמנים המוצגים בדף זה הם לפי איזור זמן GMT +2. השעה כעת היא 01:57

הדף נוצר ב 0.14 שניות עם 10 שאילתות

הפורום מבוסס על vBulletin, גירסא 3.0.6
כל הזכויות לתוכנת הפורומים שמורות © 2024 - 2000 לחברת Jelsoft Enterprises.
כל הזכויות שמורות ל Fresh.co.il ©

צור קשר | תקנון האתר