std::array

Problem: C Arrays

  • Decay to pointers to first element

  • Cannot be copied using only the language

  • Clumsy code to determine length

    • Sentinel value, like '\0' on C strings

    • Pass length together with pointer

  • Compiler cannot help on out-of-bounds

std::array To The Rescue

#include <array>
std::array<int, 3> a;
  • Implemented as struct

  • Copy done by the language

  • Does not decay to anything

  • Size is part of the type

  • Simple and efficient

Basic Usage

  • No constructor defined

  • Implemented as struct` ⟶ initializer list for free

  • Attention: default constructor leaves elements undefined

#include <gtest/gtest.h>
#include <array>

TEST(array_suite, basic)
{
    std::array<int, 3> a;                              // <-- uninitialized!
    static_assert(a.size() == 3);                      // <-- known at compile time

    a[1] = 111;
    ASSERT_EQ(a[1], 111);
}

Initialization

  • Like C aggregate (struct/array) initialization

  • ⟶ uninitialized elements initialized 0 (or default, respectively)

#include <gtest/gtest.h>
#include <array>

TEST(array_suite, initialization)
{
    std::array<int, 3> a{100, 101, 102};
    ASSERT_EQ(a[0], 100);
    ASSERT_EQ(a[1], 101);
    ASSERT_EQ(a[2], 102);

    std::array<int, 3> partly{100, 101};
    ASSERT_EQ(partly[0], 100);
    ASSERT_EQ(partly[1], 101);
    ASSERT_EQ(partly[2], 0);
}
  • Type and size deduced from initializer (since C++17?)

#include <gtest/gtest.h>
#include <array>

// since c++17?
TEST(array_suite, deducing_type)
{
    std::array a{100, 101};
    static_assert(a.size() == 2);
}

Copy And Equality

  • This easiest: std::array is a struct

  • ⟶ Compiler generated

#include <gtest/gtest.h>
#include <array>

TEST(array_suite, copy)
{
    std::array<int, 3> a1{100, 101};
    std::array<int, 3> a2{200, 201, 202};

    a1 = a2;
    ASSERT_EQ(a1[0], 200);
    ASSERT_EQ(a1[1], 201);
    ASSERT_EQ(a1[2], 202);
}
#include <gtest/gtest.h>
#include <array>

TEST(array_suite, equality)
{
    std::array<int, 3> a1 = {200, 201, 202};
    std::array<int, 3> a2 = {200, 201, 202};

    ASSERT_TRUE(a1 == a2);
}
  • constexpr, because it is so easy

  • Like most methods

#include <gtest/gtest.h>
#include <array>

TEST(array_suite, constexpr_equality)
{
    constexpr std::array<int, 3> a1 = {200, 201, 202};
    constexpr std::array<int, 3> a2 = {200, 201, 202};

    static_assert(a1 == a2);
}

Works With Range-For, Structured Binding, And Algorithms

#include <gtest/gtest.h>
#include <array>

TEST(array_suite, range_for)
{
    std::array<int, 3> a = {200, 204, 203};
    for (int _: a)
        /*do something with elem*/;
}
#include <gtest/gtest.h>
#include <array>

TEST(array_suite, structured_binding)
{
    std::array<int, 3> a = {200, 204, 203};
    auto [x,y,z] = a;
    ASSERT_EQ(x, 200);
    ASSERT_EQ(y, 204);
    ASSERT_EQ(z, 203);
}
#include <gtest/gtest.h>
#include <array>

TEST(array_suite, sort)
{
    std::array<int, 3> a = {200, 204, 203};
    std::sort(a.begin(), a.end());

    ASSERT_EQ(a[0], 200);
    ASSERT_EQ(a[1], 203);
    ASSERT_EQ(a[2], 204);
}