A C++23 laborprofil kiterjesztése nem pusztán egy újabb
-std= kapcsoló beírása a buildparancsba. Azt kell
rögzíteni, milyen bizonyítékot fogadunk el arra, hogy egy nyelvi vagy
könyvtári képesség tényleg használható a kiválasztott toolchainben. A
C++20-as alapokat itt nem ismételjük; a feature-test és build-capability
alapokhoz lásd Feature-test, standard library és
build capability (33.5), a szabvány- és dialektusszerződéshez Szabványok, dialektusok és hordozhatósági szerződés
(1.2), a reprodukálható laborhoz Reprodukálható
fordítási és diagnosztikai labor (1.3). Ez az alfejezet a C++23-ra
való átállás státusz- és ellenőrzési kérdéseit tárgyalja.
A C++23-cal kapcsolatban három különböző dolgot kell megkülönböztetni.
Az ISO/IEC 14882:2024 a kiadott, normatív szabvány. Ez mondja meg, mit jelent a C++23 nyelv és a standard könyvtár a szabvány szövege szerint. A N4950 nyilvános munkatervezet: hasznos, hozzáférhető dokumentum a szabvány tartalmának megértéséhez, de nem azonos a kiadott ISO szöveggel. A munkatervezet és a kiadott szabvány között szerkesztői és szavazási folyamatból eredő eltérések lehetnek; egy fordító pedig jellemzően nem „a teljes C++23-at” implementálja, hanem egyes javaslatokat, azok adott állapotában.
A harmadik réteg maga az implementáció. Ide tartozik a fordító, a standard könyvtár, a linker és a futásidejű környezet. Egy képesség lehet a szabványban, szerepelhet a munkatervezetben, és mégis hiányozhat a laborban használt GCC/Clang vagy libstdc++/libc++ párosból. Ezért a laborprofilban nem elég azt írni, hogy „C++23”; rögzíteni kell a konkrét fordítót, a targetet, a standard könyvtár implementációját és verzióját, valamint a vizsgált feature-test makrókat.
| Réteg | Kérdés | Tipikus bizonyíték | Korlát |
|---|---|---|---|
| Kiadott szabvány | Mi normatív? | ISO/IEC 14882:2024 | Nem mondja meg, melyik toolchain támogatja |
| Munkatervezet | Mi volt a tervezet tartalma? | N4950 | Nem azonos a kiadott szöveggel |
| Implementáció | Mit tud a labor? | feature-test, compile/link/run probe | Verzió-, target- és kapcsolófüggő |
A konkrét GCC/Clang/libstdc++/libc++ támogatási táblázatot ebben az anyagban nem tekintjük ellenőrzöttnek. A helyes minta: a laborprofil rögzíti a tényleges verziókat, a fejezet pedig olyan ellenőrzési eljárást ad, amely ezekhez a verziókhoz köthető.
__cplusplus jelentéseA C++23-as profil alapesetben explicit módon kéri a nyelvi módot:
g++ -std=c++23 -Wall -Wextra -Wpedantic -O2 probe.cpp -o probe-gcc
clang++ -std=c++23 -Wall -Wextra -Wpedantic -O2 probe.cpp -o probe-clangA -std=c++23 a célzott név. Egyes fordítókban átmeneti
névként -std=c++2b is elfogadott lehet, de ez verziófüggő,
és a laborban nem helyettesítheti a ténylegesen támogatott kapcsoló
ellenőrzését. A -std=c++23 elfogadása önmagában még nem
bizonyítja, hogy minden C++23-as képesség elérhető.
A C++23-as nyelvi módban a szabvány szerinti elvárt érték:
static_assert(__cplusplus == 202302L, "nem C++23 nyelvi mód");Ez az érték a fordítótól és a nyelvi módtól függ; a laborban
ellenőrizni kell, hogy a fordító tényleg ezt definiálja-e. A
__cplusplus == 202302L azt mutatja, hogy a fordítás nyelvi
módja C++23-ként van beállítva. Nem bizonyítja, hogy a standard könyvtár
adott headerjei elérhetők, hogy egy adott túlterhelés létezik, vagy hogy
a linker megtalálja a szükséges szimbólumot.
Érdemes külön kezelni a következőket:
__cplusplus tényleges értéke;A feature-test makró olyan előre definiált makró,
amelynek neve és értéke egy képesség jelenlétét és változatát jelzi. A
nyelvi képességeknél jellemzően __cpp_*, a könyvtári
képességeknél __cpp_lib_* alakot látsz. A könyvtári makrók
jelentős része a <version> headerből érhető el, ezért
a könyvtári ellenőrzés előtt ezt be kell include-olni.
Fontos feltétel: a makró létezése implementációs állítás, nem teljes
körű garancia. Ellenőrizni kell a nevet és a küszöbértéket is, lehetőleg
#if defined(...) && ... >= küszöb formában. A
puszta #ifdef egy korábbi, részleges vagy kísérleti értéket
is elfogadhat.
A gyakorlati ellenőrzés három szintje:
A feature-test makró ebből az első kettőt nem feltétlenül fedi le. Ezért a laborprofilban a makró mellett compile probe, link probe és rövid runtime smoke test szerepeljen.
Levezetés: miért nem elég a __cplusplus?
__cplusplus értékét a fordító a nyelvi mód alapján
állítja be.__cpp_lib_* makró a könyvtár állítását tükrözi.Az alábbi példa egy nyelvi és egy könyvtári képességre ad capability
checket, fallbackkal. A küszöbértékek szemléltetők; a laborban a
tényleges <version> és fordítási dokumentáció alapján
kell megerősíteni őket.
#include <version>
#include <cstdio>
#if defined(__cpp_explicit_this_parameter) && __cpp_explicit_this_parameter >= 202110L
# define HAVE_EXPLICIT_THIS 1
#else
# define HAVE_EXPLICIT_THIS 0
#endif
#if defined(__cpp_lib_expected) && __cpp_lib_expected >= 202202L
# include <expected>
# define HAVE_EXPECTED 1
#else
# define HAVE_EXPECTED 0
#endif
struct Probe {
int value = 42;
#if HAVE_EXPLICIT_THIS
void ping(this Probe& self) {
std::printf("explicit-this=1 expected=%d value=%d\n",
HAVE_EXPECTED, self.value);
}
#else
void ping() {
std::printf("explicit-this=0 expected=%d value=%d\n",
HAVE_EXPECTED, value);
}
#endif
};
int main() {
Probe p;
p.ping();
}A példa nem állítja, hogy bármely konkrét fordítón teszteltük. A várt
ágak: C++20 módban jellemzően a fallback ág fut; teljes C++23
támogatásnál az explicit object parameter ág; részleges könyvtári
támogatásnál a nyelvi ág igen, a HAVE_EXPECTED érték
viszont 0 lehet. A tényleges kimenetet a labor rögzíti.
A GCC és a Clang nyelvi támogatása, valamint a libstdc++ és a libc++
könyvtári támogatása külön tengely. A GCC jellemzően libstdc++-szal
dolgozik; a Clang választhat libstdc++ és libc++ között, például
-stdlib=libc++ kapcsolóval. A laborprofilnak rögzítenie
kell a tényleges párosítást, mert a „Clang támogatja” állítás önmagában
félrevezető: a kérdés az, hogy a Clang melyik standard könyvtárral,
melyik targeten, milyen kapcsolókkal.
Részleges támogatásnál előfordulhat, hogy a nyelvi szintaxis fordul,
a header létezik, de a feature-test makró hiányzik; vagy a makró
definiált, de a implementáció hiányos. Kísérleti könyvtári elemek
std::experimental névtérben vagy külön headerben lehetnek,
és nem részei a C++23 standardnak. Egyes GCC/libstdc++ kiadásokban
bizonyos C++23-as könyvtári elemek külön linkelési kapcsolót
igényelhetnek, például -lstdc++exp; ezt nem szabad
találgatni, hanem a labour dokumentálni kell. A linkelési igényt a
linker hibája vagy a könyvtár dokumentációja igazolhatja.
| Rögzítendő adat | Példa | Miért kell |
|---|---|---|
| Fordító és verzió | GCC x.y vagy Clang x.y | A nyelvi támogatás verziófüggő |
| Target | x86-64 System V, LP64 | ABI és elérhetőség targetfüggő |
| Standard flag | -std=c++23, extensions off |
A nyelvi mód pontos azonosítása |
| Standard könyvtár | libstdc++ x.y vagy libc++ x.y | A könyvtári támogatás külön tengely |
| Feature-test snapshot | __cpp_*, __cpp_lib_* értékek |
A tényleges állítás rögzítése |
| Linkelési kapcsolók | pl. -lstdc++exp, ha dokumentált |
A linkelési próba feltétele |
| Dátum | a mérés/ellenőrzés dátuma | A támogatási állapot változhat |
A C++20 profil maradjon meg baseline-ként, a C++23 pedig jelölt profilként fusson. A kettő együtt mutatja meg, hogy a fallback valóban működik-e, és hogy a C++23-as ág nem csak a fejlesztői gépen fordul-e le. Egy minimális, kétprofilos CMake-példa:
cmake_minimum_required(VERSION 3.20)
project(cpp23_probe LANGUAGES CXX)
set(PROBE_CXX_STANDARD "23" CACHE STRING "20 vagy 23")
set(CMAKE_CXX_STANDARD "${PROBE_CXX_STANDARD}")
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(probe probe.cpp)
target_compile_options(probe PRIVATE -Wall -Wextra -Wpedantic)
enable_testing()
add_test(NAME probe_runs COMMAND probe)A labor CMake-verziójában ellenőrizni kell, hogy a 23
érték ismert-e; ha nem, a standard flaget target-szinten kell átadni, és
ezt a profilban dokumentálni kell. A két profil buildje:
cmake -S . -B build20 -DPROBE_CXX_STANDARD=20 -DCMAKE_BUILD_TYPE=Debug
cmake --build build20
ctest --test-dir build20 --output-on-failure
cmake -S . -B build23 -DPROBE_CXX_STANDARD=23 -DCMAKE_BUILD_TYPE=Debug
cmake --build build23
ctest --test-dir build23 --output-on-failureA CI mátrixban érdemes legalább a „GCC + libstdc++” és a „Clang + a laborban rögzített standard könyvtár” párost futtatni, mindkettőt C++20 és C++23 módban. A C++20 futás a fallbacket ellenőrzi; a C++23 futás a jelölt képességeket. Ha a C++23-as build elbukik, nem szabad csendben C++20-ra váltani: a képességet hiányzóként kell jelölni, a fallbacknek pedig továbbra is működnie kell.
A fenti probe.cpp három tipikus profilon a
következőképpen viselkedhet. Az értékek illusztratívak, nem mért
eredmények.
| Profil | __cplusplus |
__cpp_explicit_this_parameter |
__cpp_lib_expected |
Várható ág |
|---|---|---|---|---|
| C++20 baseline | 202002L | nincs definiálva | nincs definiálva | fallback mindkettőre |
| C++23 nyelvi, részleges könyvtár | 202302L | definiált, megfelelő küszöb | nincs definiálva | explicit this, expected fallback |
| C++23 teljes laborprofil | 202302L | definiált | definiált | explicit this és expected elérhető |
A diagnózis menete: először a __cplusplus és a nyelvi
feature-test makró mondja meg, hogy a fordító mit állít. Utána a
<version> és a __cpp_lib_* makró a
könyvtár állítását mutatja. Végül a linkelési és futásidejű próba
igazolja, hogy az állítás a laborban használható. Ha a makró definiált,
de a linkelés elbukik, a profil hiányos; ha a makró nincs definiálva, a
fallback ágat kell használni, és a hiányt dokumentálni kell.
__cplusplus == 202302L értéket önmagában teljes
C++23-támogatásnak tekinteni. Ez csak a nyelvi módot jelzi.__has_include(<expected>)-et feature-test helyett
használni. A header létezhet úgy is, hogy a képesség nem teljes vagy nem
engedélyezett.#ifdef-fel ellenőrizni a
küszöbérték helyett. Egy korábbi, részleges érték is definiálhatja.-lstdc++exp vagy más linkelési kapcsoló hiányát
nyelvi hibaként diagnosztizálni. Előbb a linkerüzenetet és a könyvtár
dokumentációját kell megnézni.std::experimental, külön
header) a C++23 standard részének beállítani.A C++23 laborprofil háromrétegű: kiadott szabvány, nyilvános
munkatervezet és tényleges implementáció. A -std=c++23 és a
__cplusplus == 202302L a nyelvi módot azonosítja, de nem
bizonyítja a könyvtári képességeket. A nyelvi __cpp_* és
könyvtári __cpp_lib_* feature-test makrókat a
<version> headerrel együtt kell ellenőrizni,
lehetőleg küszöbértékkel. A támogatási állapotot compiler, standard
könyvtár, target, linkelési kapcsolók és dátum szerint kell rögzíteni. A
kétprofilos C++20/C++23 CMake és CI mátrix biztosítja, hogy a fallback
is működjön, és a C++23-as ág ne csendben, ellenőrizetlenül kerüljön be
a buildbe.
Státuszdiagnózis. Egy laborban a
__cplusplus értéke 202302L, a
<version> include-olható, de a
__cpp_lib_expected nem definiált. Mit jelent ez, és milyen
további ellenőrzéseket végzel? Írj rövid döntési fát.
Feature-test és fallback. Egészítsd ki a fejezet
Probe példáját egy static operator()-t
használó képességellenőrzéssel úgy, hogy C++20-ban is forduljon, és a
fallback viselkedése megmaradjon. Add meg a buildparancsot is.
Kétprofilos CMake. Készíts olyan CMake-beállítást, amely ugyanazt a forrást C++20 és C++23 módban is lefordítja, és mindkét profilban futtat egy füsttesztet. Fogalmazd meg, mit jelent a CI-ben, ha a C++23-as profil elbukik.
Linkelési hiba. A C++23-as build a nyelvi szintaxist elfogadja, de a linker egy standard könyvtári szimbólumra hivatkozó hibát ad. Milyen sorrendben vizsgálódsz, és milyen bizonyítékot rögzítesz a laborprofilban?
1. Megoldás. A __cplusplus == 202302L
azt valószínűsíti, hogy a nyelvi mód C++23. A hiányzó
__cpp_lib_expected azt jelzi, hogy a vizsgált standard
könyvtár nem állítja a std::expected adott változatának
elérhetőségét. Ez nem feltétlenül azt jelenti, hogy a header egyáltalán
nem létezik; lehet, hogy a makró hiányzik, a header kísérleti, vagy a
könyvtár verziója eltér. Ellenőrzési sorrend:
<version> include; __cpp_lib_expected és
küszöb; <expected> include próba; egyszerű
std::expected használat fordítása; linkelés; futásidejű
smoke test. Ha bármelyik szint hiányzik, a std::expected-et
használó kódot fallback mögé kell tenni, és a laborprofilban „részleges”
állapotként kell rögzíteni. Ellenőrzési feltétel: a fallback C++20-ban
és a C++23-as részleges profilban is fordul és fut.
2. Megoldás. Egy lehetséges kiegészítés:
#include <version>
#include <cstdio>
struct Functor {
#if defined(__cpp_static_call_operator) && __cpp_static_call_operator >= 202207L
static int operator()(int x) { return x + 1; }
#else
int operator()(int x) const { return x + 1; }
#endif
};
int main() {
std::printf("%d\n", Functor{}(41));
}A C++23-as ágban a static operator() elérhető, a
fallback ágban nem statikus tagfüggvény marad. A hívás
Functor{}(41) mindkét ágban működik. Build:
g++ -std=c++20 -Wall -Wextra -Wpedantic static_call.cpp -o static_call20
g++ -std=c++23 -Wall -Wextra -Wpedantic static_call.cpp -o static_call23Indoklás: a feature-test makró a fordító állítását ellenőrzi; a
fallback biztosítja, hogy a C++20 baseline ne törjön el. Ellenőrzési
feltétel: mindkét build sikeres, és a futtatás 42-t ad. A
küszöbértéket a laborban a tényleges <version>
alapján kell megerősíteni.
3. Megoldás. A CMake-példa már mutatja a
PROBE_CXX_STANDARD cache változót és a ctest
futtatást. A CI-ben két külön build és teszt fut:
cmake -S . -B build20 -DPROBE_CXX_STANDARD=20
cmake --build build20
ctest --test-dir build20 --output-on-failure
cmake -S . -B build23 -DPROBE_CXX_STANDARD=23
cmake --build build23
ctest --test-dir build23 --output-on-failureHa a C++23-as profil elbukik, a helyes következtetés nem az, hogy „a C++23 nem támogatott általában”, hanem hogy a rögzített compiler/stdlib/target kombinációban a vizsgált képesség nem használható. A C++20 baseline-nak továbbra is zöldnek kell lennie; a C++23-as bukást a laborprofilban a konkrét hibaüzenettel, a feature-test állapottal és a dátummal kell rögzíteni. Ellenőrzési feltétel: a C++20 build és teszt sikeres, a C++23 hiba pedig reprodukálható és dokumentált.
4. Megoldás. Először a linkerüzenetet kell
elolvasni: hiányzó szimbólum, hiányzó könyvtár vagy nem megfelelő
könyvtárverzió szerepel-e benne. Ezután ellenőrizni kell a compiler és a
standard könyvtár párosítását, a könyvtár dokumentált linkelési igényét,
például a -lstdc++exp szükségességét, majd a
buildparancsot. Ha a kapcsoló dokumentált és elérhető, a linkelési
próbát meg kell ismételni; ha nem, a képességet fallback mögé kell
tenni. A laborprofilban rögzíteni kell a fordító verzióját, a standard
könyvtár verzióját, a targetet, a linkelési kapcsolót, a linker
hibaüzenetét és a fallback működését. Ellenőrzési feltétel: a hiba vagy
dokumentált kapcsolóval megszűnik, vagy a fallback build és futás
igazoltan működik.