Narzędzia użytkownika

Narzędzia witryny


value_initialized

Boost::value_initialized<T>

Rafał Wilk

Wstęp

Boost::value_initialized<T> zapewnia generyczny sposób inicjacji deklarowanych zmiennych, klas, wskaźników i innych typów. Korzystanie z value_initialized zapewnia zinicjowanie zdeklarowanego typu wartością domyślną w momencie deklaracji.

Funkcjonalność

Zadeklarować zmienną można na wiele różnych sposobów, ale nie zawsze wartość zadeklarowanej zmiennej jest oczywista.

Przykładowo:

T zmienna;

Powyższa deklaracja nie determinuje wartości zadeklarowanej zmiennej,(często w zależności od systemu operacyjnego) zmienna ta może zostać zainicjowana wartością domyślną lub też pozostawiona z wartością bliżej nie określoną.

Można próbować na inne sposoby:

T zmienna = 0;
T klasa = T();

W tym wypadku pierwszy przykład poprawnie zainicjuje zmienną lecz nie poradzi sobie z inicjacją klasy. Drugi przykład nie może być stosowany dla klas, które dziedziczą po boost::noncopyable lub mają prywatny lub niezdefiniowany konstruktor kopiujący.

W tych wszystkich przypadkach swoje zastosowanie znajduje value_initialized:

value_initialized<T> zmienna;

Zapewnia inicjację wartością domyślną, 0 dla zmiennych artymetycznych, null'em dla wskaźników, wartością false dla typu bool, wykorzystuje domyślny konstruktor klasy itd..

Klasa value_initialized<T>

Oto jak wygląda klasa value_initialized:

template<class T>
class value_initialized
{
  public :
    value_initialized() : x() {}
    operator T&() const { return x ; }
    T& data() const { return x ; }

  private :
    unspecified x ;
} 

Udostepnia ona dwie możliwości dostępu do referencji do przechowywanego obiektu: operator T&() oraz metodę T& data().

Dodatkowo zdefiniowane została funkcja T& get( value_initialized<T> &x ), która także pozwala na dostęp do referencji obiektu.

template<class T>
T const& get ( value_initialized<T> const& x )
{
  return x.data() ;
}

template<class T>
T& get ( value_initialized<T>& x )
{
  return x.data() ;
}

Co daje łącznie trzy możliwości otzrymania referencji do obiektu i wykorzystania jej:

void fun(&T);
value_initialized<T> zmienna;

fun(zmienna);
fun(zmienna.data());
fun(get(zmienna));

Ze względu na dwie wersje funkcji get, dla wartości zmiennych i const, zaleca się właśnie ten sposób dostępu do referencji. Zapewniona zostaje kontrola dostępu i dlatego też:

value_initialized<int> zmienna ;
get(zmienna) = 1 ; // poprawne

value_initialized<int const> const_zmienna ;
get(const_zmienna) = 1 ; // błąd: obiekt typu const

value_initialized<int> const zmienna_const ;
get(zmienna_const) = 1 ; // błąd: obiekt typu const

value_initialized<int const> const const_zmienna_const ;
get(const_zmienna_const) = 1 ; // błąd: obiekt typu const

Przydatne zastosowania

value_initialized znajdzie wiele możliwości by ułatwić życie programiście, nie jest natomiast narzędziem, bez k†órego nie można żyć.

Przydatnym może okazać się inicjacja w miejscu deklaracji:

1. klas dziedziczących po boost::noncopyable lub z prywatnym konstruktorem kopiującym,

2. zmiennych arytmetycznych wartością zero,

3. wskaźników wartością null,

4. i pewnie wiele innych w zależności od potrzeb.

value_initialized.txt · ostatnio zmienione: 2009/04/30 00:02 przez rwilk