Cokolwiek, czyli Boost.Any

2010-04-17 11:52

Zasadniczo w C++ zmienne mają jednoznacznie określone typy, znane w czasie kompilacji. Istnieją oczywiście pewne mechanizmy, które zdają się tę zasadę lekko naciągać (dziedziczenie i polimorfizm, szablony), ale bez znaczącej nieścisłości można przyjąć, że jest ona prawdziwa. W języku kompilowanym nie jest to zresztą nic nadzwyczajnego.
Z kolei w językach skryptowych i interpretowanych dość powszechne jest używanie zmiennych bez określonego (tj. jawnie podanego w deklaracji) typu. To, co obecnie przechowuje liczbę, za chwilę może zawierać ciąg znaków czy odwołanie do obiektu i nie ma z tym specjalnego problemu. Typy w takich językach oczywiście istnieją, ale mają je wartości, nie zaś zmienne.

Czasami coś podobnego – czyli zmienna mogąca przechowywać wartości różnego rodzaju – przydaje się i w C++. Wtedy niektórzy przypominają sobie o void*, ale “ogólny wskaźnik na coś” rzadko jest w tym przypadku szczytem marzeń. Jego podstawową wadą jest to, że wymaga on przechowania gdzieś poza nim informacji o docelowym typie wartości, na którą pokazuje – jeśli chcemy ją później wykorzystać, rzecz jasna. Równie poważną jest fakt, że mamy tu do czynienia z wskaźnikiem; pamięć, na którą on pokazuje, musi być kiedyś zwolniona.
Dlatego też lepszym rozwiązaniem jest biblioteka Any z Boosta, umożliwiająca korzystanie ze zmiennych “typu dowolnego”. Reprezentuje go klasa boost::any, mogąca przechowywać wartości prawie dowolnego rodzaju (wymaganiem jest głównie to, by ich typy posiadały zwykły konstruktor kopiujący):

  1. #include <boost/any.hpp>
  2. boost::any any1 = 5, any2 = std::string("Ala ma kota");
  3. boost::any foo = Foo(); // o ile Foo da się kopiować

Ponieważ jednak jest to wciąż C++, a nie język skryptowy, do wartości zapisanych w obiekcie any bezpośrednio dostać się nie da. W szczególności nie można liczyć na niejawne konwersje powyższych zmiennych do typów int, string czy Foo. Zamiast tego korzysta się ze specjalnego operatora rzutowania any_cast, który pozwala na potraktowanie wartości zapisanej w any zgodnie z jej właściwym typem:

  1. int x = 1 + boost::any_cast<int>(any1);

W przeciwieństwie do void*, próba jej reinterpretacji na inny typ danych skończy się wyjątkiem. Nie trzeba jednak polegać na jego łapaniu, jeśli docelowego typu nie jesteśmy pewni: boost::any pozwala też pobrać jego type_info (tj. to, co zwraca operator typeid) bez dokonywania rzutowania.

I to w sumie wszystko jeśli chodzi o tę klasę, a jednocześnie i całą bibliotekę. Mimo swej niewątpliwej prostoty jest ona bardzo przydatna tam, gdzie potrzebujemy zmiennych przechowujących różne rodzaje wartości. Warto więc się z nią zapoznać :)

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


9 comments for post “Cokolwiek, czyli Boost.Any”.
  1. KrystianD:
    April 17th, 2010 o 16:29

    A tak prawdę mówiąc, miałeś kiedyś potrzebę użycia zmiennej “bez typu”? :)

  2. Xion:
    April 17th, 2010 o 16:37

    Interpreter języka skryptowego czy jakikolwiek system właściwości (properties) w obiektach, używany w dowolnym celu, to typowe przykłady, gdzie coś takiego się przydaje. Dla mnie aczkolwiek boost::any okazał się przydatny do nieco innego zastosowania; chwilowo nie napiszę, jakiego :)

  3. spax:
    April 17th, 2010 o 17:11

    Jak wyżej. Tyle że używałem bardziej wyspecjalizowanej struktury boost::variant :)

  4. Reg:
    April 17th, 2010 o 20:02

    Ja jakoś nie widzę zastosowania. Ale dobrze wiedzieć, że coś takiego jest. Ma jak widzę prosty interfejs, co do Boosta niepodobne ;)

  5. matma:
    April 19th, 2010 o 8:40

    A czy to nie to samo co “auto” z C++0x?

  6. świrus:
    April 19th, 2010 o 23:37

    Nie, auto służy by kompilator sam określił typ :) Tu chodzi o dynamiczne typowanie, a boost::any to proteza dorabiający ten feature to który ma nazwijmy, silną typizacje.

  7. świrus:
    April 19th, 2010 o 23:38

    fixed :P
    … ten feature do języka który ma….

  8. nilphilus:
    April 20th, 2010 o 16:13

    Całkiem fajna rzecz, czasami mi się takie coś by właśnie przydało. Eniłej, jeśli chodzi o inne języki, dynamic z C# 4.0 jest bardzo blisko tego? ;->
    [w C# 3.0 też można to osiągnąć, tylko tragicznie kod wygląda :D ]

  9. Xion:
    April 20th, 2010 o 18:30

    Jest bardzo daleko, bo wyprzedza boost::any o parę kilometrów ;-) Z kolei odpowiednikiem any w C# jest po prostu zwykły typ object.

Comments are disabled.
 


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