Dzisiejszy temat dotyczy jednego z najbardziej zdumiewających problemów poprzednich standarów języka C++. Dlaczego zdumiewających ? Między innymi dlatego, że udało mu się przetrwać dzielnie kilkanaście lat (!), pomimo swojej nieskomplikowanej natury – chodzi o podwójne nawiasy kątowe.

Ale jak to się stało ?

Spójrzmy na poniższy kod:

#include <vector>  int main() 
{       
    std::vector<std::vector<int>> myVector;     

    return 0; 
}

Widzimy tutaj deklarację zagnieżdżonego kontenera typu std::vector. Kod wygląda poprawnie, ale wynik kompilacji przedstawia się mniej więcej tak (kompilator bez wsparcia dla C++11):

 In function 'int main()': 5:32: error: '>>' should be '> >' within a nested template argument list

Błąd. Z komunikatu dowiadujemy się dokładnie, co powinniśmy zrobić, żeby wyeliminować błąd (dodanie znaku białego pomiędzy nawiasami kątowymi). Powyższy tekst jest maksimum tego, co twórcy kompilatorów zrobili dla złagodzenia problemu – wcześniej kompilatory wypluwały z siebie potok niezrozumiałych błędów i ostrzeżeń (zależnie od kontekstu) 🙂

Na czym polega problem ?

Problemem są tutaj dwa, następujące po sobie, prawe nawiasy kątowe (>>). A konkretniej to, co oznaczają one w języku C++ w różnych kontekstach. Wiemy, że taki operator jest używany w dwóch głównych kontekstach:

  • jako operator przesunięcia bitowego w prawo
  • jako operator przekierowania danych do strumienia

Mnogość zastosowań stała się problemem w przypadku pojawienia się dwóch takich znaków w kontenerach zagnieżdżonych.

Proces parsowania/interpretacji kodu przez kompilator składa się z kilku faz, które są wykonywane w określonej kolejności (analiza leksykalna, analiza składniowa, kontrola typów, itd.) i często są od siebie niezależne. W powyższym przypadku kompilator stwierdza problem, zanim się w ogóle zorientuje, że ma do czynienia z zagnieżdżoną strukturą. Niestety w takiej formie ten problem stał się częścią oficjalnego standardu języka.

Skąd to całe zamieszanie ?

Można powiedzieć, że problem był na tyle mały, że nie był wart jakiejś większej uwagi. Zresztą myślę, że właśnie dlatego zaakceptowano wcześniejszy stan rzeczy – skala pozytywnych zmian w standardzie C+98/03 była bardzo duża. Nie warto było tego porzucać z powodu jakichś małych niedociągnięć.

Ja jednak bardzo cenię sobie standard C++11 z powodu takich zmian – poradził on sobie z dużą ilością przeróżnych błędów, niedociągnięć, zaniechań i problemików. Błąd parsowania prawych nawiasów kątowych był właśnie takim potworkiem – niby mały, ale jednak również: niesamowicie irytujący, niepotrzebnie ignorowany i, co by nie mówić, jednak trochę zawstydzający 🙂