Typ std::bitset i flagi logiczne

2010-05-27 15:52

Napiszę dzisiaj o nierzadko zapominanej klasie z biblioteki standardowej C++, czyli o tytułowym zbiorze bitówstd::bitset. Działania na pojedynczych bitach nie są raczej czymś, co wykonujemy codziennie, ale zdarzają się sytuacje, gdy stanowią one najrozsądniejsze rozwiązanie w danej chwili. Takim typowym przypadkiem jest zbiór flag logicznych: kilku opcji działających jak przełączniki, których możliwą wartością jest tylko true albo false. Wszelkie API doskonale zna takie konstrukcje, czego przykładem może być metoda Clear urządzenia DirectX:

  1. dev->Clear (0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
  2.     D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);

D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER jest właśnie kombinacją flag bitowych, a dwie występujące tu stałe zostały odpowiednio zdefiniowane, by dało się je łączyć operatorem sumy bitowej |.

Używając std::bitset możemy nieco uprościć obsługę takich opcji. Zamiast deklarowania specjalnych wartości, możemy użyć zwykłego enuma, np.:

  1. enum FontStyle { Bold, Italic, Underline, FontStylesCount };

bitset jest wtedy łatwy w użyciu:

  1. void FormatText(const std::string& text,
  2.     const std::bitset<FontStylesCount>& style)
  3. {
  4.     if (style.any())  // czy jakikolwiek bit został ustawiony
  5.     {
  6.         // sprawdzenie poszczególnych flag
  7.         if (style[Bold]) { /* ... */ }
  8.         if (style[Italic]) { /* ... */ }
  9.         if (style[Underline]) { /* ... */ }
  10.     }
  11. }

Zachowana jest przy tym “kompatybilność wsteczna” w stosunku do ręcznie definiowanych stałych, jeśli chcielibyśmy z nich korzystać:

  1. #define OPT(x) (1<<(x))
  2. FormatText ("Hello World!", OPT(Bold) | OPT(Italic));&#91;/cpp]
  3. lub jeżeli jakieś zewnętrzne API, w którym programujemy, korzysta z wartości bitowych zapisywanych w typach liczbowych:
  4. &#91;cpp]std::bitset<32> lp = lParam;
  5. lp.set(30).reset(31);
  6. SendMessage (hWnd, WM_KEYDOWN, VK_UP, lp.to_ulong());

Na koniec wspomnę tylko, że aby korzystać z klasy bitset do tych lub innych zastosowań, należy wpierw dołączyć standardowy nagłówek o nazwie… bitset :)

Tags: , ,
Author: Xion, posted under Programming »


4 comments for post “Typ std::bitset i flagi logiczne”.
  1. Syriusz:
    May 27th, 2010 o 20:06

    Zastanawia mnie tylko wydajność takiego rozwiązania w porównaniu z ręcznym ustawianiem flag ;P…

  2. Liosan:
    May 28th, 2010 o 9:29

    czyli przewaga tego na zwykłym ulongiem jest taka, że mamy dodatkową składnię ( operator[] ) i nie trzeba dopisywać kolejnych potęg dwójki do enuma? Bo jeśli tak, to moim zdaniem niewarte świeczki.

  3. Xion:
    May 28th, 2010 o 17:23

    Jeśli chodzi o zastosowanie bitset do flag bitowych to hmm… zdaje się, że właśnie tak. Na szczęście ma on jeszcze kilka innych ciekawych, o których pewnie za jakiś czas napiszę :)

  4. Riddlemaster:
    May 29th, 2010 o 11:58

    Fakt jest to wygodne, ale mi np. ciężko będzie się do jego użytkowania przekonać. Operacje na bitach wyglądają lepiej w kodzie :P

Comments are disabled.
 


© 2017 Karol Kuczmarski "Xion". Layout by Urszulka. Powered by WordPress with QuickLaTeX.com.