Working with std::array Size and Indices
Access elements and query size with bounds-checked and unchecked methods.
What Is std::array Length and Indexing?
This lesson covers how to get the length of a std::array and access its elements by index. Like std::vector, std::array uses unsigned types for these operations, but its constexpr nature provides additional compile-time advantages.
Like std::vector, std::array uses unsigned types for lengths and indices, presenting similar challenges. However, std::array's constexpr nature provides additional compile-time options.
The length has type std::size_t
std::array is declared as:
template<typename T, std::size_t N>
struct array;
The length non-type template parameter N is std::size_t (unsigned). When defining an array, the length must be std::size_t or convertible to it.
Since the length must be constexpr, signed-to-unsigned conversion isn't narrowing—the compiler verifies safety at compile-time.
std::array uses size_type, which is always std::size_t
Like std::vector, std::array defines a nested typedef size_type for lengths and indices. Unlike std::vector, std::array's size_type is ALWAYS std::size_t (no customization possible).
The template parameter uses std::size_t explicitly because size_type isn't defined yet at that point. Everywhere else uses size_type.
Getting array length
Three common approaches:
Option 1: size() member function
#include <array>
#include <iostream>
int main()
{
constexpr std::array stats{ 25, 30, 18, 22 };
std::cout << "Elements: " << stats.size() << '\n';
return 0;
}
Returns unsigned size_type.
Option 2: std::size() non-member function (C++17)
#include <array>
#include <iostream>
int main()
{
constexpr std::array stats{ 25, 30, 18, 22 };
std::cout << "Elements: " << std::size(stats) << '\n';
return 0;
}
Calls the size() member function, returning unsigned size_type.
Option 3: std::ssize() non-member function (C++20)
#include <array>
#include <iostream>
int main()
{
constexpr std::array stats{ 25, 30, 18, 22 };
std::cout << "Elements: " << std::ssize(stats) << '\n';
return 0;
}
Returns a large signed integral type (typically std::ptrdiff_t).
Constexpr length from all three methods
Because std::array length is constexpr, all three functions return constexpr values even for non-constexpr arrays:
#include <array>
#include <iostream>
int main()
{
std::array bonuses{ 50, 75, 100, 150 }; // Not constexpr
constexpr int count{ std::size(bonuses) }; // OK: result is constexpr
std::cout << "Count: " << count << '\n';
return 0;
}
The conversion from constexpr std::size_t to int isn't narrowing.
This doesn't work for array parameters passed by reference due to a language defect (addressed in C++23):
#include <array>
void show(const std::array<int, 5>& arr)
{
constexpr int count{ std::size(arr) }; // Error pre-C++23!
}
Workaround: use a function template with a length non-type parameter.
Subscripting with operator[] or at()
Both operator[] (no bounds checking) and at() (runtime bounds checking) expect size_type indices:
#include <array>
#include <iostream>
int main()
{
constexpr std::array rewards{ 10, 25, 50, 100 };
std::cout << rewards[2] << '\n'; // No bounds checking
std::cout << rewards.at(2) << '\n'; // Runtime bounds checking
return 0;
}
With constexpr indices, conversion to std::size_t isn't narrowing. With non-constexpr signed indices, you'll get narrowing warnings (same issue as std::vector).
Compile-time bounds checking with std::get()
For constexpr indices, use std::get() for compile-time bounds checking:
#include <array>
#include <iostream>
int main()
{
constexpr std::array rewards{ 10, 25, 50, 100 };
std::cout << std::get<2>(rewards) << '\n'; // OK: valid index
std::cout << std::get<7>(rewards) << '\n'; // Compile error: index out of range
return 0;
}
std::get() uses a non-type template argument for the index and static_asserts that it's within bounds. Since template arguments must be constexpr, this only works with constexpr indices.
Summary
Length type: The std::array length template parameter N has type std::size_t (unsigned). Since the length must be constexpr, signed-to-unsigned conversion isn't narrowing because the compiler verifies safety at compile-time.
size_type is always std::size_t: Unlike std::vector which can customize size_type, std::array's size_type is always std::size_t. The template parameter uses std::size_t explicitly because size_type isn't defined yet at that point.
Three ways to get length: The size() member function, std::size() non-member function (C++17), and std::ssize() non-member function (C++20). All work with std::array, with std::ssize() returning a signed type.
Constexpr length: All three length functions return constexpr values for std::array, even when the array itself isn't constexpr. This allows using the length in constant expressions and static assertions.
Subscripting: Both operator[] (no bounds checking) and at() (runtime bounds checking) expect size_type indices. With constexpr indices, conversion to std::size_t isn't narrowing. With non-constexpr signed indices, you may get narrowing warnings.
Compile-time bounds checking: std::get<N>() provides compile-time bounds checking for constexpr indices. It uses a non-type template argument for the index and static_asserts validity, preventing out-of-bounds access at compile-time.
Language defect (pre-C++23): Getting the constexpr length of array parameters passed by reference doesn't work prior to C++23. Workaround: use a function template with a length non-type parameter.
The key insight is that std::array's constexpr length enables compile-time operations and safety checks that aren't possible with runtime-sized arrays like std::vector.
How did you find this lesson?
Your rating helps us improve the content.
Create an account to track your progress and access interactive exercises. Already have one? Sign in.
Working with std::array Size and Indices - Quiz
Test your understanding of the lesson.
Practice Exercises
std::array Length and Indexing
Practice working with std::array size and indexing. Learn about compile-time size, bounds checking, and safe access patterns.
Lesson Discussion
Share your thoughts and questions
No comments yet. Be the first to share your thoughts!