Pracowałem od dłuższego czasu, utrzymując poziom kompatybilności do przodu i do tyłu w moich programach C ++, aż w końcu musiałem stworzyć z niego zestaw bibliotek , który przygotowuję do wydania, został już wydany. Zasadniczo, o ile zaakceptujesz, że nie uzyskasz „doskonałej” zgodności do przodu ani w funkcjach (niektórych rzeczy po prostu nie można emulować w przód) w składni (prawdopodobnie będziesz musiał użyć makr, alternatywnych przestrzeni nazw dla niektóre rzeczy), to wszystko gotowe.
Istnieje wiele funkcji, które można emulować w C ++ 03 na poziomie wystarczającym do praktycznego użycia - i bez wszystkich problemów związanych np. Z: Boost. Heck, nawet propozycja standardów C ++ nullptr
sugeruje backport C ++ 03. Jest też TR1 na przykład dla wszystkiego C ++ 11-ale-mieliśmy-mieliśmy-zapowiedzi-przez lata. Ponadto niektóre funkcje C ++ 14, takie jak warianty asertywne, przezroczyste funktory, optional
można zaimplementować w C ++ 03!
Jedyne dwie rzeczy, o których wiem, że nie mogą być absolutnie backportowane, to constexpr i szablony variadic.
Jeśli chodzi o całą kwestię dodawania rzeczy do przestrzeni nazw std
, uważam, że to nie ma znaczenia - wcale. Pomyśl o Boost, jednej z najważniejszych i najistotniejszych bibliotek C ++ oraz ich implementacji TR1: Boost.Tr1. Jeśli chcesz ulepszyć C ++, uczyń go zgodnym z C ++ 11, a następnie z definicji przekształcasz go w coś, co nie jest C ++ 03, więc blokowanie się ponad standardem, którego i tak chcesz uniknąć , najprościej mówiąc, przynosi efekt przeciwny do zamierzonego. Puryści będą narzekać, ale z definicji nie trzeba się nimi przejmować.
Oczywiście, tylko dlatego, że nie będzie po (03) Standardowy przecież nie znaczy, że nie można próbować, czy pojedzie na wesoło obejść łamiąc go. Nie o to chodzi. Tak długo, jak zachowujesz bardzo ostrożną kontrolę nad tym, co jest dodawane do std
przestrzeni nazw i masz kontrolę nad środowiskami, w których używane jest twoje oprogramowanie (tj.: Testuj!), Nie powinno być żadnej nieocenionej szkody. Jeśli to możliwe, zdefiniuj wszystko w osobnej przestrzeni nazw i dodaj using
do niej tylko dyrektywy, aby std
nie dodawać niczego poza tym, co „absolutnie” musi wejść. Co, IINM, jest mniej więcej tym, co robi Boost.TR1.
Aktualizacja (2013) : jako żądanie pierwotnego pytania i widząc niektóre komentarze, których nie mogę dodać z powodu braku powtórzeń, oto lista funkcji C ++ 11 i C ++ 14 oraz ich stopień przenośności do C ++ 03:
nullptr
: w pełni możliwe do wdrożenia, biorąc pod uwagę oficjalne zaplecze Komitetu; prawdopodobnie będziesz musiał podać także niektóre specjalizacje type_traits, aby został rozpoznany jako typ „rodzimy”.
forward_list
: w pełni możliwe do wdrożenia, chociaż wsparcie dla alokatora zależy od tego, co może zapewnić implementacja Tr1.
- Nowe algorytmy (kopiowanie partycji itp.): W pełni implementowalne.
- Konstrukcje kontenerów z sekwencji nawiasów klamrowych (np .:)
vector<int> v = {1, 2, 3, 4};
: w pełni implementowalne, choć bardziej wyraziste niż byśmy tego chcieli.
static_assert
: prawie w pełni możliwe do wdrożenia, gdy jest zaimplementowany jako makro (musisz tylko uważać na przecinki).
unique_ptr
: prawie w pełni możliwe do wdrożenia, ale będziesz również potrzebować pomocy przy wywoływaniu kodu (do przechowywania ich w kontenerach itp.); patrz jednak poniżej.
- referencje wartości: prawie w pełni możliwe do wdrożenia w zależności od tego, ile oczekujesz od nich (np .: Zwiększ ruch).
- Iteracja Foreach: prawie w pełni możliwa do wdrożenia, składnia nieco się różni.
- używanie funkcji lokalnych jako argumentów (na przykład: transform): prawie w pełni możliwe do wdrożenia, ale składnia będzie się wystarczająco różnić - na przykład funkcje lokalne nie są zdefiniowane w witrynie wywołania, ale tuż przed.
- jawne operatory konwersji: możliwe do wdrożenia do praktycznych poziomów (jawna konwersja), zobacz „ express_cast ” Imperfect C ++ ; ale integracja z funkcjami językowymi, które
static_cast<>
mogą być prawie niemożliwe.
- przekazywanie argumentów: możliwe do wdrożenia do praktycznych poziomów, biorąc pod uwagę powyższe informacje na temat odwołań do wartości, ale musisz zapewnić przeciążenie N funkcji, przyjmując argumenty, które można przekazywać.
- move: możliwe do wdrożenia do praktycznych poziomów (patrz dwa wyżej). Oczywiście, aby skorzystać z tego, należy użyć kontenerów i obiektów modyfikujących.
- Przydziały z zakresem: Naprawdę niemożliwe do wdrożenia, chyba że Twoja implementacja Tr1 może w tym pomóc.
- typy znaków wielobajtowych: Naprawdę nie można go wdrożyć, chyba że Tr1 może cię wspierać. Ale w zamierzonym celu lepiej jest polegać na bibliotece specjalnie zaprojektowanej do radzenia sobie z tą sprawą, takiej jak OIOM, nawet jeśli używasz C ++ 11.
- Listy argumentów variadic: możliwe do wdrożenia z pewnymi problemami, należy zwrócić uwagę na przekazywanie argumentów.
noexcept
: zależy od funkcji kompilatora.
- Nowa
auto
semantyka i decltype
: zależy od funkcji twojego kompilatora - np __typeof__
.:
- typy liczb całkowitych wielkości (
int16_t
itp.): zależą od funkcji kompilatora - lub możesz przekazać je na Portable stdint.h.
- atrybuty typu: zależy od funkcji kompilatora.
- Lista inicjalizacyjna: Według mojej wiedzy nie można jej wdrożyć; jeśli jednak chcesz zainicjować kontenery sekwencjami, patrz wyżej na temat „konstrukcji kontenerów”.
- Aliasing szablonów: nie do zrealizowania o mojej wiedzy, ale i tak jest to niepotrzebna funkcja, i mamy
::type
szablony na zawsze
- Szablony Variadic: Nie do wdrożenia według mojej wiedzy; close jest domyślnie argumentem szablonu, który wymaga N specjalizacji itp.
constexpr
: Nie można wdrożyć o mojej wiedzy.
- Jednolita inicjalizacja: Nie można jej wdrożyć, ale gwarantowana domyślna inicjalizacja konstruktora może zostać zaimplementowana ala inicjalizacja wartości Boost.
- C ++ 14
dynarray
: w pełni implementowalny.
- C ++ 14
optional<>
: prawie w pełni możliwy do wdrożenia, o ile kompilator C ++ 03 obsługuje ustawienia wyrównania.
- Przezroczyste funktory C ++ 14: prawie w pełni implementowalne, ale kod klienta prawdopodobnie będzie musiał jawnie użyć np .:,
std::less<void>
aby działał.
- C ++ 14 nowych wariantów asercji (takich jak
assure
): w pełni implementowalne, jeśli chcesz aserty, prawie w pełni implementowalne, jeśli zamiast tego chcesz włączyć rzuty.
- Rozszerzenia krotek C ++ 14 (pobierz element krotki według typu): w pełni implementowalne, a nawet nie uda się go skompilować z dokładnymi przypadkami opisanymi w propozycji funkcji.
(Oświadczenie: kilka z tych funkcji jest zaimplementowanych w mojej bibliotece backportów C ++, którą podłączyłem powyżej, więc myślę, że wiem o czym mówię, kiedy mówię „w pełni” lub „prawie w pełni”).