Menu
Coddy logo textTech

constexpr ו־consteval

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 87 מתוך 104.

ב-C++ אפשר לבצע חישובים בזמן הקומפילציה במקום בזמן הריצה, מה שעשוי לשפר משמעותית את הביצועים. מילת המפתח constexpr (C++11) ומילת המפתח consteval (C++20) מאפשרות לך לשלוט במועד שבו ביטויים מוערכים.

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

#include <iostream>

constexpr int square(int n) {
    return n * n;
}

int main() {
    constexpr int compileTime = square(5);  // מחושב בזמן הקומפילציה
    
    int x = 7;
    int runtime = square(x);  // מחושב בזמן הריצה
    
    std::cout << compileTime << "\n";  // 25
    std::cout << runtime << "\n";      // 49
}

כשצריך להבטיח חישוב בזמן הקומפילציה, השתמשו ב-consteval. פונקציית consteval חייבת להפיק קבוע — קריאה לה עם ערכים בזמן ריצה היא שגיאת קומפילציה:

consteval int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

int main() {
    constexpr int result = factorial(5);  // OK: 120 חושב בזמן הקומפילציה
    
    // int x = 5;
    // int bad = factorial(x);  // ERROR: x אינו קבוע
}

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

challenge icon

אתגר

קל

תארגנו את הקוד שלכם בשלושה קבצים:

  • MathUtils.h: הגדירו את פונקציות המתמטיקה שלכם לחישוב בזמן הידור.

    צרו את הפונקציות הבאות:

    • cube: פונקציית constexpr שמקבלת int ומחזירה את החזקה השלישית שלו (n * n * n)
    • triangularNumber: פונקציית constexpr שמחשבת את המספר המשולשי ה-n באמצעות הנוסחה n * (n + 1) / 2. במשימה הזו נקרא לה רק בהקשר של חישוב בזמן הידור, ונשמור את התוצאה במשתנה constexpr.
    • sumOfSquares: פונקציית constexpr שמקבלת שני מספרים שלמים ומחזירה את סכום הריבועים שלהם (a*a + b*b)
  • Config.h: צרו מבנה תצורה באמצעות קבועים בזמן הידור.

    הגדירו מבנה Config עם בנאי constexpr שמקבל שלושה מספרים שלמים: width, height ו-depth. שמרו אותם כחברים ציבוריים. הוסיפו גם מתודה constexpr בשם volume() שמחזירה את width * height * depth.

    מתחת למבנה, צרו קבוע גלובלי מסוג constexpr בשם DEFAULT_CONFIG ואתחלו אותו בערכים 10, 20 ו-5.

  • main.cpp: קראו שני מספרים שלמים מהקלט שמייצגים ערכים בזמן ריצה.

    תחילה, הדגימו חישוב בזמן הידור על ידי יצירת משתני constexpr:

    • שמרו את cube(4) במשתנה constexpr והדפיסו: Cube of 4: [value]
    • שמרו את triangularNumber(10) במשתנה constexpr והדפיסו: 10th triangular number: [value]
    • הדפיסו את נפח ברירת המחדל של התצורה: Default volume: [value]

    לאחר מכן, הדגימו שפונקציות constexpr יכולות לפעול גם בזמן ריצה, באמצעות שני ערכי הקלט שלכם:

    • קראו ל-cube() עם הקלט הראשון והדפיסו: Cube of [input]: [result]
    • קראו ל-sumOfSquares() עם שני ערכי הקלט והדפיסו: Sum of squares: [result]

לדוגמה, עבור הקלטים 3 ו-4:

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25

עבור הקלטים 5 ו-12:

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169

נסו בעצמכם

#include <iostream>
#include "MathUtils.h"
#include "Config.h"

using namespace std;

int main() {
    // קראו שני מספרים שלמים מהקלט
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: הדגימו חישוב בזמן קומפילציה
    // צרו משתנה constexpr ששומר את התוצאה של cube(4) והדפיסו: "Cube of 4: [value]"
    
    // TODO: צרו משתנה constexpr ששומר את התוצאה של triangularNumber(10)
    // והדפיסו: "10th triangular number: [value]"
    
    // TODO: הדפיסו את עוצמת הקול של תצורת ברירת המחדל: "Default volume: [value]"
    
    // TODO: הדגימו שימוש בפונקציות constexpr בזמן ריצה
    // קראו ל־cube() עם input1 והדפיסו: "Cube of [input1]: [result]"
    
    // TODO: קראו ל־sumOfSquares() עם שני ערכי הקלט
    // והדפיסו: "Sum of squares: [result]"
    
    return 0;
}
quiz iconבחנו את עצמכם

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

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C++ אונליין