📜 ⬆️ ⬇️

Calculating the maximum number in the array at compile time

Hello habr!

Not so long ago, it was necessary to calculate the maximum length of several specified lines at the compilation stage. It is necessary to allocate memory for the char [] array, so that it fits any line from the specified ones. It is logical to assume that if the system is well designed, no computation at the compilation stage is needed, you can use dynamic allocation using std :: auto_ptr or std :: string, but this is not the case. The structure in which the char [] buffer is stored must be a POD type.

In essence, the task is to determine the maximum number in the array at the compilation stage. In this topic, I will show how to do this in the standard c ++ 03 and c ++ 11. During the search for solutions, I found two articles that helped me solve the problem: habrahabr.ru/post/166201 , habrahabr.ru/post/38622 .

So, to bypass all the specified strings, add them into an array:
const char str1[] = "Anna"; const char str2[] = "Denis"; const char str3[] = "Vladimir"; const char str4[] = "Alexey"; const char *arr[] = { str1, str2, str3, str4 }; 

Now, sizeof (arr) returns 16, and sizeof (arr [2]) returns 4. Alas, we lost information about the size of the rows in each element of the arr array. The trick in order to put the sizeof results of each line in the array also does not work, because at the compilation stage pointers dereferencing operations are not allowed. In general, you need to look for something more powerful than ordinary arrays ...
The solution to this problem is to make an array emulation using structures. Add the lengths of all strings into separate structures and link them with Loki :: TypeList.
 struct str_1 { static const int size = sizeof(str1); }; struct str_2 { static const int size = sizeof(str2); }; struct str_3 { static const int size = sizeof(str3); }; struct str_4 { static const int size = sizeof(str4); }; typedef LOKI_TYPELIST_4(str_1, str_2, str_3, str_4) List; 

Now we can bypass this list of types and pull out the size from each of them.
')
The final version of c ++ 03
 struct str_1 { static const int size = sizeof(str1); }; struct str_2 { static const int size = sizeof(str2); }; struct str_3 { static const int size = sizeof(str3); }; struct str_4 { static const int size = sizeof(str4); }; typedef LOKI_TYPELIST_4(str_1, str_2, str_3, str_4) List; #define GetMaxLen(TypeList) \ \ template<class Cur_Type> \ struct len \ { \ static const int cur_size = Cur_Type::Head::size; \ static const int next_size = len<Cur_Type::Tail>::max_size; \ static const int max_size = cur_size > next_size ? cur_size : next_size ; \ }; \ \ template<> \ struct len<NullType> \ { \ static const int max_size = 0; \ }; \ \ static const int ml = len<TypeList>::max_size; \ GetMaxLen(List); //  *.cpp // LOKI_STATIC_CHECK((ml == sizeof(str3)), size_is_wrong); 


This option is not the most convenient, since such a structure is easy to maintain with a relatively small number of lines. However, as this number increases, it is possible to simply forget to add the appropriate structure for the line.
On the standard c ++ 11 everything turns out much prettier and more convenient. Plus, you don’t need to be “perverted” with structures and type lists. We are allowed to dereference pointers, but only constexpr and inside the constexpr function.

Final version with ++ 11
 constexpr const char str1[] = "Anna"; constexpr const char str2[] = "Denis"; constexpr const char str3[] = "Vladimir"; constexpr const char str4[] = "Alexey"; constexpr const char *arr[] = { str1, str2, str3, str4 }; #define GetMaxLenght(array) \ constexpr unsigned char str_len(const char* const str) \ {\ return *str ? (1 + str_len(str + 1)) : 0;\ }\ \ template <int index> \ struct MaxLenght\ {\ static const int prev_size = MaxLenght<index-1>::max_size;\ static const int cur_size = str_len(array[index]);\ static const int max_size = cur_size > prev_size ? cur_size : prev_size;\ };\ \ template <>\ struct MaxLenght<-1>\ {\ static const int max_size = 0;\ };\ static const int AmountStr = sizeof(array) / sizeof(array[0]);\ static const int array##_max_size = MaxLenght<AmountStr-1>::max_size; GetMaxLenght(arr); //  *.cpp // static_assert((arr_max_size == 8), "Error"); 



PS I hope this article will help someone.
PPS I would be glad if someone offers a solution using boost or some other tools.

Source: https://habr.com/ru/post/192736/


All Articles