How does std::array know it's size?

I wrote this script so I could look at data structures. When I looked at a std::array<char,3> I was surprised to see that it's size was three. So how does it know its size?

When I tried to look at its size(), it gave me an error:

error: cannot take the address of an rvalue of type 'std::array::size_type' (aka 'unsigned long') address_view(std::cout, &(a1.size()), sizeof(a1.size()));


I was also confused to see that it's size is a rvalue, because my understanding of rvalue is it's a temporary value.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include<iostream>
#include<limits>
#include<cstring>
#include<iomanip>
#include<stdexcept>
#include<cctype>
#include<array>
#include<vector>
#include<typeinfo>


inline void print_hex(std::ostream& os, const unsigned char& c) { 
    os << std::setw(2) << std::setfill('0') << std::hex << (c & 0xff) << ' ' ;
}

inline void print_char(std::ostream& os, const unsigned char& c) { 
    if (!std::isprint(c)) os << "   "; 
    else os << std::setw(2) << std::setfill(' ') << c << ' ';
}

template<typename T>
void address_view(std::ostream& os, T* var, size_t size) {

    os << "The passed size of var is: " << std::dec <<size << '\n'
       << "The address is: " << std::hex << (void*)var << '\n';

    const int max{100};
    size = size > max ? max : size;
    unsigned char view[max];
    std::memcpy(view, var, size);

    for(size_t i = 0; i != size ; ++i) print_hex(os, view[i]);
    os << '\n';

    for(size_t i = 0; i != size ; ++i) print_char(os, view[i]);
    os << '\n';
}

int main() try {

    std::array<char,3> a1{'a','b','c'};

    address_view(std::cout, &a1, sizeof(a1));
//    address_view(std::cout, &(a1.size()), sizeof(a1.size()));

}
catch (std::exception& e) {
    std::cout << "Caught: " << typeid(e).name() << '\n'
              << "Message: " << e.what()        << '\n';
    return 1;
}
Last edited on
Works fine with VS2019


The passed size of var is: 3
The address is: 0018FF2C
61 62 63
 a  b  c

I'm sorry, I guess wasn't clear.

If the data structure is only 3 bytes each containing a value there doesn't seem to me to be any information about the size. How does it know it's size? Where is a1.size() in the data structure?

I've written my own array classes, but I always store the size.



The second template argument tells the array the size (number of elements). Since it is never changed it is a constant.
Never mind, the answer just became obvious to me.
Last edited on
Thank coder777, It came to me probably while you were typing.
With a template function taking a std::array as a parameter using 2 placeholders works. One for the data type, the other for the size of the std::array. For example:
1
2
template<typename T, size_t N>
void PrintArray(std::array<T, N> const&);


Doing that makes it easy to pass a std::array without specifying its size.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
#include <array>
#include <string>

template<typename T, size_t N>
void PrintArray(std::array<T, N> const&);

template <typename T, size_t N>
std::ostream& operator<<(std::ostream&, std::array<T, N> const&);

int main()
{
   std::array<int, 5> a { 1, 2, 3, 4, 5 };
   PrintArray(a);

   std::array<double, 3> b { 6.1, 7.275, 8.3333333333 };
   std::cout << b << '\n';

   std::array<std::string, 4> c { "Test", "Word", "Hello", "Good-bye" };
   std::cout << c << '\n';
}

template<typename T, size_t N>
void PrintArray(std::array<T, N> const& arr)
{
   std::cout << "The array contains " << arr.size() << " elements\n";

   for (const auto itr : arr)
   {
      std::cout << itr << ' ';
   }
   std::cout << "\n\n";
}

template <typename T, size_t N>
std::ostream& operator<<(std::ostream& os, std::array<T, N> const& arr)
{
   os << "The array contains " << arr.size() << " elements.\n";

   for (const auto itr : arr)
   {
      os << itr << ' ';
   }
   os << '\n';

   return os;
}
address_view(std::cout, &a1, sizeof(a1));

That would give an erroneous size if your std::array was any type other than char.

Unlike the language operator sizeof, which returns the size in bytes, this member function returns the size of the array in terms of number of elements.
http://www.cplusplus.com/reference/array/array/size/

Use std::array::size() if you want the number of elements.
Topic archived. No new replies allowed.