שאלה ב CPP

make clean

New member
תודה על כל התגובות

אחרי קריאת התגובות וקצת ניסויים שעשיתי אני נוטה לחשוב שהקומפיילר באמת משאיר קטעים של template לסוף הקומפילציה (אחרי סוג של עיבוד ראשוני בלבד ) ולכן כשהוא מייצר את הקוד הרלוונטי הוא כבר מכיר גם את ההגדרה של A ולכן אין לו בעיה .
יכול להיות שזה באמת תלוי מימוש ושתקן השפה לא תומך בזה.

מצורף קוד שמתקמפל (שברור שיקרוש בזמן ריצה) שמראה שלקומפיילר אין בעיה לקרוא לפונקציות שמכניסות A ל list למרות שהוא עדיין לא מוגדר למרות שלהגדיר A ממש ברור שהוא לא יכול.

#include <list>

using namespace std;

struct A;

void foo(){

list<A> lA;
A* pa=0;
list<A>::iterator itA=lA.begin();
lA.push_front(*pa);
lA.push_front(*itA);

lA.insert(itA , *itA );

//A a=*itA;
//pa =newA(*itA);

}


struct A{

};
 
לא הבנתי מה ניסית להדגים בקוד הזה

אתה לא חושב שהקומפיילר "קורא" את הקוד שלך במעבר יחיד מלמעלה למטה כמו ספר, נכון?
 

make clean

New member
אותי זה מפתיע

במקור קופילר לC כן היה אמור להצליח לקמפל ממעבר יחיד. עדיין ב CPP אי אפשר להשתמש במבנה שלא הוגדר אלא רק בפוינטר או רפרנס אליו ולכן היה טבעי לחשוב שגם template יהיה כפוף למגבלה הזו .
בעיני זה מוזר ששורה כמו :

pa =newA(*itA)

לא תתקמפל אבל
lA.push_front(*itA);

שברור שבשבילה אמור להיות איפשהו קוד שמקצה אוביקט מטיפוס A כן מתקמפלת.
 

BravoMan

Active member
כי new דורש קריאה לפונקצית בנאי, ולכן

הקומפיילר צריך לדעת שיש פונקציה כזו שגם מקבלת מצביע לטיפוס של itA.

מצד שני, בשורה שנייה "ידוע" שקיימת פונקציה push_front כי היא בהגדרה של list (וההגדרה של list שלמה ונקראה כבר ב-include).

אגב, הקוד שצריפת לא ירוץ בעצמו.
חסרה לו נקודת כניסה (פונקציה main) ובהתאם למה שתכניס שם, ייתכן שנראה התנהגויות מעניינות.
 

make clean

New member
אבל במימוש של push_front חייבת להיות

קריאה לCTOR של A (וגם פנייה ל alocator שיקצה מקום בגודל A) ובכל זאת זה עובר קומפילציה.
ההגדרה של list לא שלמה - היא רק template וכדי ליצור list/iterator
של A הקומפילר צריך "לקמפל" קוד מתאים לפחות פונקציות הנדרשות.

העדר פונקציית main לא מונע קומפילציה אלא link וברור שאי אפשר להריץ מה שכתבתי - הפוינטרים והאיטרטורים לא מאותחלים.
 

make clean

New member
לא ברורה לי כוונת השאלה

אם התכוונת לשאול על ה template אז הקומפיילר אמור ליצור קוד של המחלקה list<A>
. הקוד הזה לא היה קיים בקובץ בינארי שהלינקר לוקח אלא אמור להווצר "במיוחד" עבור המבנה A.

אם התכוונת לשאול באיזה קומפילר אני מקמפל אז כתבתי קודם - G++ גרסא 4.6.3
 
כן, רציתי לדעת באיזה קומפיילר

אני מניח שהשאלה האם זה יתן שגיאת הידור או לא תלויה ב:
1. מהדר.
2. מימוש STL.

עכ"פ עוד לא הבנתי על מה הפליאה - אני יכול לדמיין בקלות קוד לרשימה שלא יצטרך שום מידע קונקרטי על האובייקט בזמן קומפילציה כדי לבצע push.
לחלופין, אני יכול לדמיין שזכותו של המהדר לקרוא את הקובץ עד סופו, ורק אז לקפוץ לקימפול מפורש של templates.
אף אחד לא אוסר על המהדר לעבור יותר מפעם אחת על קבצים, או "להשאיר" יחידת קימפול לאחר כך, למיטב ידיעתי.

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

make clean

New member
אני גם חושב כמו הכיוון השני שלך

אני לא מצליח לדמיין קוד שמוסיף אבר מטיפוס A לרשימה בלי להכיר אותו ( צריך לפחות לדעת את הגודל שלו ואת ה CCTOR שלו).
 
אגב זה רעיון גרוע להשתמש ב-struct ריק

כשלעצמו זה "פיצ'ר" שהתמיכה/היעדר תמיכה בו תלויית קומפיילרים, וקשה להעריך איזו (אם) הודעת שגיאה הוא ייצר.
כיוון שזה לא מה שאתה בודק כרגע - תשתמש ב-struct יותר מסביר פנים.
 
למעלה