Algorytmy STL na tablicach

Często w programach napisanych w C do pobierania rozmiaru tablic alokowanych przez kompilator na stosie stosuje się prostą konstrukcję z operatorem sizeof, opakowana w makro:

#define SizeOfArray(array)	sizeof(array) / sizeof(array[0])

W C++ zamiast makra lepiej wykorzystać wzorzec, a wtedy można to przedstawić tak:

template<typename T, size_t N>
inline size_t SizeOfArray(const T (&)[N]) {
	return N;
}

Wersja cpplusowa jest bezpieczniejsza, próba wywołania SizeOfArray() na wskaźniku zakończy się bledem w czasie kompilacji, w przeciwieństwie do makra, które dopiero da znać w run-timie.

To tyle słowami wstępu. Zresztą nie chciałem zbytnio o tym pisać, jedynie wspomnieć o prostej możliwości używania algorytmów z STL-a na zwykłych tablicach. Większość algorytmów działa poprawnie na wskaźnikach zamiast iteratorów.

int array[] = { 1, 2, 3, 4, 5 };
std::copy(array, array + SizeOfArray(array), std::ostream_iterator<int>(std::cout, " "));

Dla nieco lepszego i czytelniejszego kodu, można dopisać 2 szablonowe funkcje służące do pobierania "iteratorów" dla tablicy, bez konieczności pamiętania o dodawaniu rozmiaru przy wskaźniku "na koniec".

template<typename T, size_t N>
inline T* begin(T (&array)[N]) {
	return array;
}
 
template<typename T, size_t N>
inline T* end(T (&array)[N]) {
	return array + N;
}

Teraz wystarczy:

std::copy(begin(array), end(array), std::ostream_iterator<int>(std::cout, " "));

Idąc dalej można specjalizować powyższe funkcje również dla zwykłych iteratorów, wtedy będzie można używać funkcji begin() i end() w jednakowy sposób dla zwykłych tablic i kontenerów z biblioteki STL.

Napsianie tego zostawiam czytelnikom (jeśli jacys są ;p)jako zadanie domowe ;)

Na jakimś forum przypadkiem trafiłem właśnie na takie specjalizacje, ponoć w starej (?) implementacji array w boost było to używane, ale nie mogę tego potwierdzić.

5 przemyśleń nt. „Algorytmy STL na tablicach”

  1. Dziwne, bo przeciez operator sizeof jak i wzorce są rozwijane w czasie kompilacji.
    Zrobilem testy i dla tablicy z 5 intami, VC9 i GCC3.4.x dla obu wersji wygenerowal podobny kod z liczba 5, bez zadnych dodatkowych operacji jakie musialyby byc wykonane w czasie dzialania.

    No tak, Count bylby lepszy ;p
    Odwiedzam co jakis czas Twoja strone, tam chyba kiedys widzialem to rozwiazanie ;)

  2. Operacji dodatkowych nie ma, ale takie cos nie przejdzie:
    int array2[SizeOfArray(array)];
    Po prostu kompilator nie jest w stanie okreslic rezultatu (teoretycznie moglby, ale w C++ tego nie zrobi).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *