C++ Linked Lists   «Prev  Next»
Lesson 3A safe array
ObjectiveGrouping arrays in a class

Grouping Class Arrays using C++23

In C++23, grouping arrays of classes can be done using several modern techniques that offer both performance and expressive clarity. Here's how you can do it depending on your use case:
  1. Using `std::array` for Fixed-Size Class Arrays
    If your array size is known at compile time:
    #include <array>
    #include <iostream>
    
    class Student {
    public:
        std::string name;
        int age;
    };
    
    int main() {
        std::array<Student, 3> students{{
            {"Alice", 20},
            {"Bob", 22},
            {"Charlie", 21}
        }};
    
        for (const auto& s : students) {
            std::cout << s.name << " is " << s.age << " years old.\n";
        }
    }
    
  2. Using `std::vector` for Dynamic-Size Class Arrays
    If the number of objects can grow or shrink at runtime:
    #include <vector>
    #include <string>
    #include <iostream>
    
    class Book {
    public:
        std::string title;
        int year;
    };
    
    int main() {
        std::vector<Book> library = {
            {"The Hobbit", 1937},
            {"1984", 1949},
            {"Dune", 1965}
        };
    
        library.emplace_back("Neuromancer", 1984);
    
        for (const auto& b : library) {
            std::cout << b.title << " (" << b.year << ")\n";
        }
    }
    

  1. Using `std::span` to Group Subarrays
    C++20 and later (including C++23) introduced `std::span` for lightweight, non-owning views of arrays:
    #include <span>
    #include <iostream>
    
    class Point {
    public:
        int x, y;
    };
    
    void printGroup(std::span<Point> group) {
        for (const auto& p : group) {
            std::cout << "(" << p.x << "," << p.y << ")\n";
        }
    }
    
    int main() {
        Point points[] = {{1,2}, {3,4}, {5,6}, {7,8}};
        printGroup(points);  // All points
        printGroup({points, 2});  // First 2 only
    }
    
  2. Using Structured Bindings with `std::tuple` or `std::pair`
    For grouping heterogeneous class arrays:
    #include <tuple>
    #include <string>
    #include <iostream>
    
    class Engine { /*...*/ };
    class Wheels { /*...*/ };
    class Body { /*...*/ };
    
    int main() {
        std::tuple<Engine, Wheels, Body> car;
        auto& [e, w, b] = car; // Structured binding in C++17+
    }
    
  3. Group by Member with Ranges (C++23)
    You can group elements by a member or a lambda using ranges and views (C++23 with ranges and projections):
    #include <ranges>
    #include <vector>
    #include <iostream>
    
    struct User {
        std::string role;
        std::string name;
    };
    
    int main() {
        std::vector<User>
    


Summary Table
Technique Use Case Ownership Feature
std::array Fixed size, known at compile time Owns data C++11+
std::vector Dynamic size, resizable Owns data C++98+
std::span Views into existing arrays No C++20+
std::tuple Group different class types Owns data C++11+
Ranges/Views Functional-style grouping/filter No C++20–23
Examine creating "has-a" relationship by making the safe array class a member of another class. Now that we have created a safe array, let's use our class vect as a member of the class pair_vect. Using a class as a member of another class is known as the has-a relationship. Complicated objects can be designed from simpler ones by incorporating them with the has-a relationship.
#include "vect.h" //the safe array class
//from the previous lesson

class pair_vect {
 public:
  pair_vect(int i) : a(i), b(i), size(i){ }
  int& first_element(int i);
  int& second_element(int i);
  int ub()const {return size -1;}
  private:
  vect a, b;
  int size;
};

int& pair_vect::first_element(int i){ 
return a.element(i); 
}

int& pair_vect::second_element(int i)
{ return b.element(i);}

Notice how the pair_vect constructor is a series of initializers. The initializers of the vect members a and b invoke vect::vect(int). Let's use the pair_vect class to build a table of age and weight relationships.
int main()
{
int     i;
pair_vect age_weight(5);  //age and weight

cout << "table of age, weight\n";
for (i = 0; i <= age_weight.ub(); ++i) {
age_weight.first_element(i) = 21 + i;
age_weight.second_element(i) = 135 + i;
cout << age_weight.first_element(i) << ","
<< age_weight.second_element(i)<< endl;
}
}

SEMrush Software