עבור לתוכן

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

Featured Replies

פורסם

למשל פונקציה שמקבלת T ו-G (שניהם משתנים מסוג כלשהו), ומחזירה את הסכום שלהם.

אם G ו-T הם int/double/float/long או כל משתנה אחר שמחזיק מספר, אז זה יהיה מעולה. אבל אם למשל אחד מהם יהיה int והשני string יתקבל דבר בלתי רצוי.

פורסם

אם אתה רוצה לאפשר לקבל משתנים מסוג מספרי ו-string, אתה יכול כמובן.

השאלה היא מה זה דבר בלתי רצוי? כמובן שהקומפיילר לא יכול לדעת.

יש כמה אופציות:

1. לא להשתמש ב-templates.

2. להשתמש ולבדוק בזמן ריצה האם T הוא String.

3. ליצור פונקציה טמפלטית שתכסה את רוב המקרים ולטפל נקודתית במקרים בעייתיים. תוכל לכתוב פונקציה עם חתימה דומה רק שמקבלת כפרמטר String וטיפוס נוסף טמפלטי.

פורסם

מה שיקרה פשוט זה שהקוד לא יתקמפל, בדיוק כמו אם תנסה להגדיר int ו-string ואז לחבר ביניהם.

העניין ב-templates הוא כזה: כשאתה מגדיר template, אז לא נוצרת שום מחלקה באמת. המחלקה נוצרת ומתקמפלת רק כשאתה ממש משתמש ב-template. לדוגמה, המחלקה <vector<T היא מחלקה טמפלייטית. כשאתה מגדיר <vector<int אז מה שקורה הוא שהקומפיילר יוצר "עותק" של המחלקה vector, כשהוא מחליף את כל המופעים של T ב-int, ומנסה לקמפל אותו. אותו דבר כשאתה מגדיר <vector<string - הקומפיילר יוצר עותק של המחלקה כשהוא מחליף את T ב-string ומנסה לקמפל. בסופו של דבר אתה מקבל שתי מחלקות נפרדות לחלוטין, כאילו הגדרת מחלקה בשם vector_int ו-vector_string.

בדוגמה שלך, נניח שהגדרת את המחלקה הזו (סלח לי אם הקוד לא מדויק מבחינה תחבירית, הרבה זמן לא כתבתי ++C):


class MyClass<T,G> {
public:
T f(T t, G g) { return t+g; }
}

כשתבוא ליצור משתנה מטיפוס <MyClass<string,int אז הקומפיילר כאמור יחליף את T ב-string ואת G ב-int, וינסה לקמפל את התוצאה. כלומר הוא ינסה לקמפל קוד שנראה ככה:


class MyClass_string_int {
public:
string f(string t, int g) { return t+g; }
}

כיוון שלא קיים אופרטור + בין string ו-int (למיטב זכרוני), הקומפיילר יזרוק שגיאת קומפילציה.

פורסם

הנה כלל אצבע: templates מתאימים יותר לקונטיינרים ואלגוריתמים סטנדרטיים (sort, swap וכולי). לדברים אחרים ירושה ופולימורפיזם עשוי להתאים יותר.

ממליץ להרחיב בנושא - בגרסאות האחרונות של ++C ישנם פיצ'רים כמו decltype, rtti, static_cast\dynamic_cast

פורסם
  • מחבר

תודה

התכוונתי לפונקציה עם תבנית, ולא למחלקה. למשל בקוד הבא:

template <class T , class G>

void sum(T num1, G num2)
{
cout << "Sum: " << num1 + num2 << endl;

}

יש אפשרות לבדוק בתוך הפונקציה האם T או G הם מחרוזת? (במקום להעמיס פונקציה מיוחדת בנפרד)

נערך על-ידי א

פורסם

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

פורסם
  • מחבר

סתם סיקרן אותי אם זה אפשרי, לא בשביל שום דבר ספציפי. תודה

פורסם

האמת היא שזה אפשרי כבר בזמן קומפילציה.

תחפש enable_if.

צריך להשתמש או בBOOST(אוסף ספריות C++) או בקומפיילר שתומך בC++11.

פורסם

אפשרי בעזרת template specialization למשל באופן הבא:


#include <iostream>
#include <string>

using namespace std;

template <typename T1, typename T2>
void print_sum(T1 n1, T2 n2)
{
cout << n1 + n2 << endl;
}

template<>
void print_sum(string s1, string s2)
{
cout << "called print_sum() for a string" << endl;
}

int main()
{
print_sum(3.5, 4);

string s1("Hello ");
string s2("World");
print_sum(s1, s2);
}





פורסם

כבר הצעתי את זה, אבל טוב שנת קוד כדוגמה.

3. ליצור פונקציה טמפלטית שתכסה את רוב המקרים ולטפל נקודתית במקרים בעייתיים. תוכל לכתוב פונקציה עם חתימה דומה רק שמקבלת כפרמטר String וטיפוס נוסף טמפלטי.

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים