Is there a way to find how many values an array has? Detecting whether or not I\'ve reached the end of an array would also work.
There's also the TR1/C++11/C++17 way (see it Live on Coliru):
const std::string s[3] = { "1"s, "2"s, "3"s };
constexpr auto n = std::extent< decltype(s) >::value; // From <type_traits>
constexpr auto n2 = std::extent_v< decltype(s) >; // C++17 shorthand
const auto a = std::array{ "1"s, "2"s, "3"s }; // C++17 class template arg deduction -- http://en.cppreference.com/w/cpp/language/class_template_argument_deduction
constexpr auto size = std::tuple_size_v< decltype(a) >;
std::cout << n << " " << n2 << " " << size << "\n"; // Prints 3 3 3
One of the most common reasons you would end up looking for this is because you want to pass an array to a function, and not have to pass another argument for its size. You would also generally like the array size to be dynamic. That array might contain objects, not primitives, and the objects maybe complex such that size_of() is a not safe option for calculating the count.
As others have suggested, consider using an std::vector or list, etc in instead of a primitive array. On old compilers, however, you still wouldn't have the final solution you probably want by doing simply that though, because populating the container requires a bunch of ugly push_back() lines. If you're like me, want a single line solution with anonymous objects involved.
If you go with STL container alternative to a primitive array, this SO post may be of use to you for ways to initialize it: What is the easiest way to initialize a std::vector with hardcoded elements?
Here's a method that I'm using for this which will work universally across compilers and platforms:
Create a struct or class as container for your collection of objects. Define an operator overload function for <<.
class MyObject;
struct MyObjectList
{
std::list<MyObject> objects;
MyObjectList& operator<<( const MyObject o )
{
objects.push_back( o );
return *this;
}
};
You can create functions which take your struct as a parameter, e.g.:
someFunc( MyObjectList &objects );
Then, you can call that function, like this:
someFunc( MyObjectList() << MyObject(1) << MyObject(2) << MyObject(3) );
That way, you can build and pass a dynamically sized collection of objects to a function in one single clean line!
Instead of using the built in array function aka:
int x[3] = {0, 1, 2};
you should use the array class and the array template. Try:
#include <array>
array<type_of_the_array, number_of_elements_in_the_array> Name_of_Array = {};
So now if you want to find the length of the array, all you have to do is using the size function in the array class.
Name_of_Array.size();
and that should return the length of elements in the array.
#include <iostream>
int main ()
{
using namespace std;
int arr[] = {2, 7, 1, 111};
auto array_length = end(arr) - begin(arr);
cout << "Length of array: " << array_length << endl;
}
Since C++11, some new templates are introduced to help reduce the pain when dealing with array length. All of them are defined in header <type_traits>
.
std::rank<T>::value
If T
is an array type, provides the member constant value equal to the number of dimensions of the array. For any other type, value is 0.
std::extent<T, N>::value
If T
is an array type, provides the member constant value equal to the number of elements along the N
th dimension of the array, if N
is in [0, std::rank<T>::value
). For any other type, or if T
is array of unknown bound along its first dimension and N
is 0, value is 0.
std::remove_extent<T>::type
If T
is an array of some type X
, provides the member typedef type equal to X
, otherwise type is T
. Note that if T
is a multidimensional array, only the first dimension is removed.
std::remove_all_extents<T>::type
If T
is a multidimensional array of some type X
, provides the member typedef type equal to X
, otherwise type is T
.
To get the length on any dimension of a multidimential array, decltype
could be used to combine with std::extent
. For example:
#include <iostream>
#include <type_traits> // std::remove_extent std::remove_all_extents std::rank std::extent
template<class T, size_t N>
constexpr size_t length(T(&)[N]) { return N; }
template<class T, size_t N>
constexpr size_t length2(T(&arr)[N]) { return sizeof(arr) / sizeof(*arr); }
int main()
{
int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};
// New way
constexpr auto l1 = std::extent<decltype(a)>::value; // 5
constexpr auto l2 = std::extent<decltype(a), 1>::value; // 4
constexpr auto l3 = std::extent<decltype(a), 2>::value; // 3
constexpr auto l4 = std::extent<decltype(a), 3>::value; // 0
// Mixed way
constexpr auto la = length(a);
//constexpr auto lpa = length(*a); // compile error
//auto lpa = length(*a); // get at runtime
std::remove_extent<decltype(a)>::type pa; // get at compile time
//std::remove_reference<decltype(*a)>::type pa; // same as above
constexpr auto lpa = length(pa);
std::cout << la << ' ' << lpa << '\n';
// Old way
constexpr auto la2 = sizeof(a) / sizeof(*a);
constexpr auto lpa2 = sizeof(*a) / sizeof(**a);
std::cout << la2 << ' ' << lpa2 << '\n';
return 0;
}
BTY, to get the total number of elements in a multidimentional array:
constexpr auto l = sizeof(a) / sizeof(std::remove_all_extents<decltype(a)>::type);
Or put it in a function template:
#include <iostream>
#include <type_traits>
template<class T>
constexpr size_t len(T &a)
{
return sizeof(a) / sizeof(typename std::remove_all_extents<T>::type);
}
int main()
{
int a[5][4][3]{{{1,2,3}, {4,5,6}}, { }, {{7,8,9}}};
constexpr auto ttt = len(a);
int i;
std::cout << ttt << ' ' << len(i) << '\n';
return 0;
}
More examples of how to use them could be found by following the links.
You have a bunch of options to be used to get a C array size.
int myArray[] = {0, 1, 2, 3, 4, 5, 7};
1) sizeof(<array>) / sizeof(<type>):
std::cout << "Size:" << sizeof(myArray) / sizeof(int) << std::endl;
2) sizeof(<array>) / sizeof(*<array>):
std::cout << "Size:" << sizeof(myArray) / sizeof(*myArray) << std::endl;
3) sizeof(<array>) / sizeof(<array>[<element>]):
std::cout << "Size:" << sizeof(myArray) / sizeof(myArray[0]) << std::endl;