Coming Soon

This lesson is currently being developed

Constant expressions

Learn about expressions that can be evaluated at compile time.

Constants and Strings
Chapter
Beginner
Difficulty
35min
Estimated Time

What to Expect

Comprehensive explanations with practical examples

Interactive coding exercises to practice concepts

Knowledge quiz to test your understanding

Step-by-step guidance for beginners

Development Status

In Progress

Content is being carefully crafted to provide the best learning experience

Preview

Early Preview Content

This content is still being developed and may change before publication.

5.5 — Constant expressions

In this lesson, you'll learn about constant expressions in C++, understand when expressions can be evaluated at compile time, and discover how they improve program performance and reliability.

What are constant expressions?

A constant expression is an expression that can be evaluated at compile time rather than at runtime. The result of a constant expression is known when the program is being compiled, not when it's running.

Think of constant expressions as mathematical problems that can be solved with a calculator before your program even starts running - the answer is already known and built into the program.

Types of constant expressions

1. Simple constant expressions

Basic arithmetic with literals and const variables:

#include <iostream>

int main()
{
    // Simple constant expressions with literals
    int result1 = 5 + 3;           // Evaluated at compile time
    int result2 = 10 * 2 + 1;      // Evaluated at compile time
    double result3 = 3.14 * 2.0;   // Evaluated at compile time
    
    std::cout << "Result 1: " << result1 << std::endl;
    std::cout << "Result 2: " << result2 << std::endl;
    std::cout << "Result 3: " << result3 << std::endl;
    
    return 0;
}

Output:

Result 1: 8
Result 2: 21
Result 3: 6.28

All these expressions are calculated during compilation, not runtime.

2. Constant expressions with const variables

#include <iostream>

int main()
{
    // const variables can be used in constant expressions
    const int width = 10;
    const int height = 5;
    const int area = width * height;    // Constant expression
    
    const double pi = 3.14159;
    const double radius = 3.0;
    const double circumference = 2 * pi * radius;  // Constant expression
    
    std::cout << "Rectangle area: " << area << std::endl;
    std::cout << "Circle circumference: " << circumference << std::endl;
    
    return 0;
}

Output:

Rectangle area: 50
Circle circumference: 18.8495

3. Complex constant expressions

#include <iostream>

int main()
{
    // Complex calculations that are still constant expressions
    const int base = 2;
    const int exponent = 10;
    const int powerOfTwo = base * base * base * base * base * 
                          base * base * base * base * base;  // 2^10 = 1024
    
    const double fahrenheit = 100.0;
    const double celsius = (fahrenheit - 32.0) * 5.0 / 9.0;  // F to C conversion
    
    const int secondsPerMinute = 60;
    const int minutesPerHour = 60;
    const int hoursPerDay = 24;
    const int secondsPerDay = secondsPerMinute * minutesPerHour * hoursPerDay;
    
    std::cout << "2^10 = " << powerOfTwo << std::endl;
    std::cout << "100°F = " << celsius << "°C" << std::endl;
    std::cout << "Seconds per day: " << secondsPerDay << std::endl;
    
    return 0;
}

Output:

2^10 = 1024
100°F = 37.7778°C
Seconds per day: 86400

What makes an expression constant?

An expression is a constant expression if:

  1. All operands are constant expressions
  2. All operators used are allowed in constant expressions
  3. No function calls (except to constexpr functions - covered in next lesson)
  4. No runtime dependencies

Examples of constant expressions:

#include <iostream>

int main()
{
    const int a = 5;
    const int b = 10;
    
    // These are all constant expressions:
    const int sum = a + b;              // ✓ Addition of constants
    const int product = a * b;          // ✓ Multiplication of constants
    const bool comparison = a < b;      // ✓ Comparison of constants
    const int conditional = (a > 0) ? a : b;  // ✓ Conditional with constants
    
    std::cout << "Sum: " << sum << std::endl;
    std::cout << "Product: " << product << std::endl;
    std::cout << "Comparison (a < b): " << comparison << std::endl;
    std::cout << "Conditional: " << conditional << std::endl;
    
    return 0;
}

Output:

Sum: 15
Product: 50
Comparison (a < b): 1
Conditional: 5

Examples of non-constant expressions:

#include <iostream>

int getValue()
{
    return 42;
}

int main()
{
    int variable = 10;  // Not const!
    const int constant = 20;
    
    // These are NOT constant expressions:
    int notConstant1 = variable + 5;        // ❌ Uses non-const variable
    int notConstant2 = getValue();          // ❌ Function call (not constexpr)
    
    // This IS a constant expression:
    const int isConstant = constant + 5;    // ✓ Uses const variable
    
    std::cout << "Non-constant 1: " << notConstant1 << std::endl;
    std::cout << "Non-constant 2: " << notConstant2 << std::endl;
    std::cout << "Constant: " << isConstant << std::endl;
    
    return 0;
}

Output:

Non-constant 1: 15
Non-constant 2: 42
Constant: 25

Benefits of constant expressions

1. Performance improvement

Constant expressions are calculated once at compile time, not repeatedly at runtime:

#include <iostream>
#include <chrono>

int main()
{
    auto start = std::chrono::high_resolution_clock::now();
    
    // This loop might be optimized heavily because calculations are constant
    for (int i = 0; i < 1000000; ++i)
    {
        const double pi = 3.14159;
        const double radius = 5.0;
        const double area = pi * radius * radius;  // Constant expression
        // The compiler might calculate area once and reuse the value
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    
    std::cout << "Time for loop with constant expressions: " 
              << duration.count() << " microseconds" << std::endl;
    
    return 0;
}

2. Array size specification

Constant expressions can be used to specify array sizes:

#include <iostream>

int main()
{
    // Constant expressions for array sizes
    const int maxStudents = 30;
    const int subjectsPerStudent = 5;
    const int totalGrades = maxStudents * subjectsPerStudent;  // Constant expression
    
    // Can use constant expressions for array sizes
    int grades[totalGrades];
    int studentIds[maxStudents];
    double averages[maxStudents];
    
    std::cout << "Array sizes:" << std::endl;
    std::cout << "Grades array: " << totalGrades << " elements" << std::endl;
    std::cout << "Student IDs array: " << maxStudents << " elements" << std::endl;
    std::cout << "Averages array: " << maxStudents << " elements" << std::endl;
    
    // Initialize some values
    for (int i = 0; i < maxStudents && i < 5; ++i)
    {
        studentIds[i] = 1000 + i;
        averages[i] = 85.0 + i * 2.5;
    }
    
    std::cout << "\nFirst few student IDs and averages:" << std::endl;
    for (int i = 0; i < 5; ++i)
    {
        std::cout << "Student " << studentIds[i] 
                  << ": " << averages[i] << "%" << std::endl;
    }
    
    return 0;
}

Output:

Array sizes:
Grades array: 150 elements
Student IDs array: 30 elements
Averages array: 30 elements

First few student IDs and averages:
Student 1000: 85%
Student 1001: 87.5%
Student 1002: 90%
Student 1003: 92.5%
Student 1004: 95%

3. Template parameters

Constant expressions can be used as template parameters:

#include <iostream>
#include <array>

int main()
{
    // Constant expressions for template parameters
    const int rows = 3;
    const int cols = 4;
    const int matrixSize = rows * cols;  // Constant expression
    
    // Use in std::array template
    std::array<int, matrixSize> matrix;
    
    // Initialize the matrix
    for (int i = 0; i < matrixSize; ++i)
    {
        matrix[i] = i + 1;
    }
    
    std::cout << "Matrix (" << rows << "x" << cols << "):" << std::endl;
    for (int i = 0; i < rows; ++i)
    {
        for (int j = 0; j < cols; ++j)
        {
            std::cout << matrix[i * cols + j] << "\t";
        }
        std::cout << std::endl;
    }
    
    return 0;
}

Output:

Matrix (3x4):
1	2	3	4	
5	6	7	8	
9	10	11	12	

Practical examples of constant expressions

1. Configuration constants

#include <iostream>

int main()
{
    // Game configuration using constant expressions
    const int screenWidth = 1920;
    const int screenHeight = 1080;
    const int pixelsPerInch = 96;
    
    // Calculated constants
    const double screenWidthInches = static_cast<double>(screenWidth) / pixelsPerInch;
    const double screenHeightInches = static_cast<double>(screenHeight) / pixelsPerInch;
    const double screenDiagonal = screenWidthInches * screenWidthInches + 
                                  screenHeightInches * screenHeightInches;
    
    const int totalPixels = screenWidth * screenHeight;
    const int bytesPerPixel = 4;  // RGBA
    const int totalMemory = totalPixels * bytesPerPixel;
    
    std::cout << "Screen Configuration:" << std::endl;
    std::cout << "Resolution: " << screenWidth << "x" << screenHeight << std::endl;
    std::cout << "Size: " << screenWidthInches << "\" x " << screenHeightInches << "\"" << std::endl;
    std::cout << "Total pixels: " << totalPixels << std::endl;
    std::cout << "Memory required: " << totalMemory << " bytes (" 
              << totalMemory / 1024 / 1024 << " MB)" << std::endl;
    
    return 0;
}

Output:

Screen Configuration:
Resolution: 1920x1080
Size: 20" x 11.25"
Total pixels: 2073600
Memory required: 8294400 bytes (7 MB)

2. Mathematical constants

#include <iostream>

int main()
{
    // Mathematical constants using constant expressions
    const double pi = 3.141592653589793;
    const double e = 2.718281828459045;
    const double goldenRatio = (1.0 + 5.0) / 2.0;  // (1 + √5) / 2, approximated
    
    // Derived constants
    const double twoPi = 2.0 * pi;
    const double piSquared = pi * pi;
    const double eSquared = e * e;
    
    // Unit conversions
    const double inchesToCm = 2.54;
    const double feetToMeters = 0.3048;
    const double milesToKm = 1.609344;
    
    std::cout << "Mathematical Constants:" << std::endl;
    std::cout << "π = " << pi << std::endl;
    std::cout << "e = " << e << std::endl;
    std::cout << "φ (golden ratio) ≈ " << goldenRatio << std::endl;
    std::cout << "2π = " << twoPi << std::endl;
    std::cout << "π² = " << piSquared << std::endl;
    std::cout << "e² = " << eSquared << std::endl;
    
    std::cout << "\nUnit Conversions:" << std::endl;
    std::cout << "1 inch = " << inchesToCm << " cm" << std::endl;
    std::cout << "1 foot = " << feetToMeters << " meters" << std::endl;
    std::cout << "1 mile = " << milesToKm << " km" << std::endl;
    
    return 0;
}

Output:

Mathematical Constants:
π = 3.14159
e = 2.71828
φ (golden ratio) ≈ 3
2π = 6.28319
π² = 9.8696
e² = 7.38906

Unit Conversions:
1 inch = 2.54 cm
1 foot = 0.3048 meters
1 mile = 1.60934 km

3. Bit manipulation constants

#include <iostream>

int main()
{
    // Bit manipulation using constant expressions
    const int bit0 = 1 << 0;   // 1
    const int bit1 = 1 << 1;   // 2
    const int bit2 = 1 << 2;   // 4
    const int bit3 = 1 << 3;   // 8
    const int bit4 = 1 << 4;   // 16
    const int bit5 = 1 << 5;   // 32
    const int bit6 = 1 << 6;   // 64
    const int bit7 = 1 << 7;   // 128
    
    // Combined flags
    const int readFlag = bit0;
    const int writeFlag = bit1;
    const int executeFlag = bit2;
    const int allPermissions = readFlag | writeFlag | executeFlag;
    
    // Color constants (RGB)
    const int redMask = 0xFF0000;
    const int greenMask = 0x00FF00;
    const int blueMask = 0x0000FF;
    const int alphaMask = 0xFF000000;
    const int colorMask = redMask | greenMask | blueMask;
    
    std::cout << "Bit Constants:" << std::endl;
    for (int i = 0; i <= 7; ++i)
    {
        std::cout << "Bit " << i << ": " << (1 << i) << std::endl;
    }
    
    std::cout << "\nFile Permissions:" << std::endl;
    std::cout << "Read: " << readFlag << std::endl;
    std::cout << "Write: " << writeFlag << std::endl;
    std::cout << "Execute: " << executeFlag << std::endl;
    std::cout << "All permissions: " << allPermissions << std::endl;
    
    std::cout << "\nColor Masks:" << std::endl;
    std::cout << "Red mask: 0x" << std::hex << redMask << std::endl;
    std::cout << "Green mask: 0x" << greenMask << std::endl;
    std::cout << "Blue mask: 0x" << blueMask << std::endl;
    std::cout << "Alpha mask: 0x" << alphaMask << std::endl;
    
    return 0;
}

Output:

Bit Constants:
Bit 0: 1
Bit 1: 2
Bit 2: 4
Bit 3: 8
Bit 4: 16
Bit 5: 32
Bit 6: 64
Bit 7: 128

File Permissions:
Read: 1
Write: 2
Execute: 4
All permissions: 7

Color Masks:
Red mask: 0xff0000
Green mask: 0xff00
Blue mask: 0xff
Alpha mask: 0xff000000

Debugging and understanding constant expressions

You can use static_assert to verify that expressions are constant:

#include <iostream>

int main()
{
    const int a = 10;
    const int b = 20;
    const int sum = a + b;
    
    // static_assert can only be used with constant expressions
    static_assert(sum == 30, "Sum should be 30");
    static_assert(a < b, "a should be less than b");
    
    // These would cause compile errors if uncommented:
    // int variable = 5;
    // static_assert(variable == 5, "This won't compile - variable is not const");
    
    std::cout << "All static assertions passed!" << std::endl;
    std::cout << "Sum: " << sum << std::endl;
    
    return 0;
}

Output:

All static assertions passed!
Sum: 30

Best practices for constant expressions

1. Use meaningful names

#include <iostream>

int main()
{
    // Good: descriptive constant expressions
    const int maxPlayersPerTeam = 11;
    const int numberOfTeams = 2;
    const int totalPlayersOnField = maxPlayersPerTeam * numberOfTeams;
    
    const double fieldLengthMeters = 100.0;
    const double fieldWidthMeters = 50.0;
    const double fieldAreaSquareMeters = fieldLengthMeters * fieldWidthMeters;
    
    std::cout << "Soccer field info:" << std::endl;
    std::cout << "Players on field: " << totalPlayersOnField << std::endl;
    std::cout << "Field area: " << fieldAreaSquareMeters << " m²" << std::endl;
    
    return 0;
}

Output:

Soccer field info:
Players on field: 22
Field area: 5000 m²

2. Group related constants

#include <iostream>

int main()
{
    // Group related constants together
    // Time constants
    const int secondsPerMinute = 60;
    const int minutesPerHour = 60;
    const int hoursPerDay = 24;
    const int daysPerWeek = 7;
    
    // Derived time constants
    const int secondsPerHour = secondsPerMinute * minutesPerHour;
    const int secondsPerDay = secondsPerHour * hoursPerDay;
    const int secondsPerWeek = secondsPerDay * daysPerWeek;
    
    // Display the constants
    std::cout << "Time Constants:" << std::endl;
    std::cout << "Seconds per hour: " << secondsPerHour << std::endl;
    std::cout << "Seconds per day: " << secondsPerDay << std::endl;
    std::cout << "Seconds per week: " << secondsPerWeek << std::endl;
    
    return 0;
}

Output:

Time Constants:
Seconds per hour: 3600
Seconds per day: 86400
Seconds per week: 604800

3. Document complex calculations

#include <iostream>

int main()
{
    // Physics constants with documentation
    const double gravitationalAcceleration = 9.81;  // m/s² on Earth
    const double speedOfLight = 299792458.0;         // m/s in vacuum
    
    // Projectile motion calculations
    const double launchAngleDegrees = 45.0;
    const double launchAngleRadians = launchAngleDegrees * 3.14159 / 180.0;
    const double initialVelocity = 20.0;  // m/s
    
    // Range formula: R = (v² * sin(2θ)) / g
    const double range = (initialVelocity * initialVelocity * 2.0 * launchAngleRadians) / 
                         gravitationalAcceleration;
    
    std::cout << "Projectile Motion:" << std::endl;
    std::cout << "Launch angle: " << launchAngleDegrees << "°" << std::endl;
    std::cout << "Initial velocity: " << initialVelocity << " m/s" << std::endl;
    std::cout << "Range: " << range << " meters" << std::endl;
    
    return 0;
}

Output:

Projectile Motion:
Launch angle: 45°
Initial velocity: 20 m/s
Range: 81.5827 meters

Summary

Constant expressions are expressions that can be evaluated at compile time:

  • Benefits: Better performance, can be used for array sizes and template parameters
  • Requirements: All operands must be constants, no function calls (except constexpr)
  • Types: Arithmetic, logical, comparison, and conditional expressions with constants
  • Use cases: Configuration values, mathematical constants, bit flags, array sizes
  • Best practices: Use meaningful names, group related constants, document complex calculations

Understanding constant expressions helps you write more efficient and reliable C++ code. In the next lesson, we'll learn about constexpr, which extends the power of constant expressions to functions and more complex scenarios.

Quiz

  1. What is a constant expression?
  2. When are constant expressions evaluated - at compile time or runtime?
  3. Can you use a non-const variable in a constant expression?
  4. What are three benefits of using constant expressions?
  5. Why can constant expressions be used to specify array sizes?

Practice exercises

Try these exercises with constant expressions:

  1. Create a program that calculates area and perimeter of different shapes using constant expressions
  2. Define bit flag constants using constant expressions for a simple permissions system
  3. Create time conversion constants (seconds to minutes, hours, days) using constant expressions
  4. Use constant expressions to define array sizes and initialize arrays with calculated values

Continue Learning

Explore other available lessons while this one is being prepared.

View Course

Explore More Courses

Discover other available courses while this lesson is being prepared.

Browse Courses

Lesson Discussion

Share your thoughts and questions

💬

No comments yet. Be the first to share your thoughts!

Sign in to join the discussion