WG21 komitean tapaaminen Tokiossa 2024
Mikä komitea, miten kehitys toimii?
C++:n standardia ylläpitää ja kehittää ISO/IEC:n alainen komitea, jota tuttavallisemmin kutsutaan WG21:ksi. Standardi itsessään on kasa mustaa valkoisella, joka kertoo miten C++ -kääntäjien kuuluu toimia. Tämän perusteella sitten eri toimijat voivat tehdä kääntäjästä implementaation. Yleisimmät kolme implementaatiota ovat Microsoftin MSVC, GNU:n g++, ja LLVM:n clang, joita sitten käytetään C++ -ohjelmien tekemiseen. Standardin virallinen versio on ISO:n maksumuurin takana, mutta uusin vedos on sama paperi ja saatavilla julkisesti useammassa muodossa.
C++:n standardikomitea pitää tapaamisen kolme kertaa vuodessa, ja julkaisee uuden version kielestä kolmen vuoden välein. Tällä hetkellä työn alla ovat C++26 ja C++29. Komitean sisällä taas on erillisiä työryhmiä, jotka keskittyvät kapeammin eri aihetta koskeviin uudistuksiin ennen kuin ne tuodan isomman porukan äänestettäviksi. Tarkempaa kuvausta komitean rakenteesta löytyy isocpp:n sivuilta.
Viimeisimmät tapaamiset tätä kirjoittaessa ovat olleet marraskuussa 2023 Konassa, Havaijilla WorldQuantin järjestämän, ja juuri pari päivää sitten loppunut Woven by Toyotan järjestämä Tokion tapaaminen.
Suomesta komitean toimintaan pääsee osallistumaan SFS/SR317:n kautta. Sama koskee useampaa muutakin kieltä, kuten esimerkiksi Adaa, Cobolia, FORTRANIA ja C:tä.
Miten minä tähän liityn?
Aloitin hitaasti aktiivisemman C++:n kehityksen seuraamisen noin 15 vuotta sitten kun C++11:sta (silloimmin C++0x:ää) oltiin julkaisemassa. Enemmän tai vähemmän yllättäen liityin loppujen lopuksi itsekin WG21:eeni Timur Doumlerin innoittamana, ja Tokion tapaaminen oli ensimmäinen jossa olin kasvotusten muiden WG21:n jäsenien kanssa enkä vain osallistumassa Zoomin välityksellä. Kiitoksia työnantajalleni Buutille matkan sponsoroinnista.
Komitean sisällä on kolme ryhmää joiden toiminnassa yritän olla mukana. Nämä ovat SG20 (Opetus), SG6 (Numeriikka) ja EWG (Kielen kehitys), mainitussa järjestyksessä. Tämä antaa ehkä vähän näkymää siihen millä perusteella valitsen mistä tulee tännekkin kirjoitettua, ja jos joku muu osa-alue kiinnosta enemmän niin tällaisia "matkaraportteja" löytyy enemmänkin. Komitean virallisen epävirallinen laajempi yhteenveto löytyy Redditistä.
Mitäs siellä sitten tehtiin?
Vahvistettuja uutuuksia C++26:een
17 uutta ehdotusta hyväksyttiin C++26:een. Osa näistä oli hyvinkin simppeleitä kuten se, että tyhjä std::println()
tulostaa tyhjän rivinvaihdon, mutta luettelen muutaman joita pidän itse mielenkiintoina.
Erroneous behaviour for uninitialized reads
Paperin oma yhteenveto on erittäin hyvin selitetty, ja suosittelen lukemaan sen kiinnostuneille. Paperin idea on lisätä erronous behaviour -käsite standardiin.
Reading an uninitialized value is never intended and a definitive sign that the code is not written correctly and needs to be fixed. At the same time, we do give this code well-defined behaviour, and if the situation has not been diagnosed, we want the program to be stable and predictable. This is what we call erroneous behaviour.
Ja käyttää tätä alkajaisiksi alustamattomien arvojen lukuun. Kaikin puolin laatua 🎉
Trivial infinite loops are not Undefined Behavior
C++:ssa päättymättömät silmukat ovat olleet UB:tä hyvin pitkään, ja kääntäjät ovat saaneet tehdä kummallisia kikkoja optimoinnin ja suorituskyvyn niitten tapauksessa. Ryöstääkseni esimerkin suoraan paperista
#include <iostream>
int main() {
while (true);
}
void unreachable() {
std::cout << "Hello world?\n";
}
Ja tulokset
[ananas@mellori (0) ~]$ clang --version
clang version 17.0.0 (https://github.com/llvm/llvm-project.git 68a09c929003bf6af41162ed9e6dc4713d96a997)
Target: x86_64-unknown-linux-gnu
Thread model: posix
InstalledDir: /usr/local/bin
[ananas@mellori (0) ~]$ clang++ wtf.cpp -O2 && ./a.out
Hello world?
[ananas@mellori (192) ~]$
Mikään ei estänyt kääntäjiä käsittelemästä tätä tilannetta odotetusti aiemminkaan (ja sekä gcc että MSVC tietääkseni hoitivat tämän aina kunnialla), mutta nyt standardissa sanotaan suoraan että tätä ei saa tapahtua tyhjien silmukoiden tapauksessa.
= delete("should have a reason");
Paatuneet kirjastonkirjoittajat kuten allekirjoittanut tykkäävät yrittää parantaa kirjastosta karanneita virheilmoituksia, ja tämän paperin hyväksymisen jälkeen se muuttui aavistuksen verran helpommaksi. Kaikessa yksinkertaisuudesaan, C++26:ssa voidaan kirjoittaa jotain tyyliin
class handle
{
handle(const handle&) = delete("cannot copy a handle, use move instead");
};
ja loppukäyttäjä saa suoraan järkevän ilmoituksen virheestä.
Unified Function Call Syntax peruttu
Maanantaina aloitusseremonioiden jälkeen olin valmistautunut lähinnä Herb Sutterin UFCS:n vastutukseen, mistä oma vastineemme löytyy täältä.
Kaikki Suomen aktiiviset edustajat ovat aika samaa mieltä siitä että koko ehdotus tulisi polttaa ja tuhkat ampua aurinkoon, kuten vastineen nimilistasta voikin päätellä. UFCS olisi saattanut olla hyvä idea jos se olisi pultattu kieleen 40 vuotta sitten. Kieliä joissa vastaava ominaisuus on täysin käyttökelpoinen on olemassa, mutta kyseisen ominaisuuden pulttaaminen kiinni kieleen tässä välissä vaatii aika paljon vakuuttelua että uskoisin ettei se olisi täysi katastrofi. Onnistuimme parissa minuutissa keksimään kasan bugeja joita kääntäjä ei voi suoraan tarkistaa esimerkki-implementaatiosta, joista vain pari päätyi vastineeseen. Omasta mielestäni kyseinen ominaisuus myös tekee C++:n kaltaisesta kielestä entistä vaikeamman hahmottaa, ja C++:n ei todellakaan tarvitse olla yhtään vaikeampi sillä alalla kuin se jo on.
Taistelu kuitenkin siirtyi eteenpäin, sillä Herb Sutter ei halunnut esittää paperiaan vastaamatta vastineeseen, joten katsotaan miten pitkälle tässä ketjussa päästään.
Isot jutut; Reflektio ja kontraktit
Isot asiat joita on suunniteltu C++26:een, eli reflektio ja kontraktit veivät molemmat kokonaisen päivän EWG:ltä. Valitettavasti itse missasin reflektiopäivän lähes kokonaan, koska numeriikka meni sen kanssa päällekkäin. Reflektio tuntuu etenevän aikataulussa, eikä sille ole vastustusta jonka kuvittelisi pysäyttävän koko homman. Toivoisin itse lähinnä parempaa syntaksia, mutten ole äänestämässä kyseistä ominaisuutta vastaan nykymuodossakaan. Syntaksi on vain hieman enemmän kuin vähän vihamielisen oloinen kieleen vähemmän tutustuneille kehittäjille ja kun otin asian esiin yleinen kommentti oli "eihän sitä tarvi heti alussa opettaa".
Oma vastaukseni tuohon alkoi olla tonnin seteli-ilme. Voi olla että joudun vielä kirjoittamaan ja esittämään oman paperini aiheesta.
Kontraktit vaikuttavat hemmetin siistiltä ominaisuudelta, mutta niissä on pari hyvin mielipiteitä jakavaa ominaisuutta ja EWG tuntuu hyvin jakaantuneelta nykyisen esityksen suhteen. Oma luotto ei riitä siihen että näistä erimielisyyksistä päästäisiin eroon sillä aikataululla, että kontraktit nähtäisiin välttämättä C++26:ssa, mutta ratkaisuehdotuksia oli jo ilmassa. En ole itse vakuuttunut nykyisestä ehdotuksesta, koska epäilen että se on nykyisessä muodossaan taas yksi lisäominaisuus jonka iso osa koodikannoista vain bännää suoriltaan joko syystä tai ilman sellaista. Toivoisin että kyseinen ominaisuus tulisi kieleen siten, että AUTOSAR-maailma ja reaaliaikaohjelmoijat pystyisivät käyttämään kyseistä ominaisuutta ilman suurempia murheita, enkä jäänyt käsitykseen että olisin lähellekään ainoa tämän mielipiteen kanssa. Microsoftilla oli myös omat näkemyksensä asiasta, enkä ole erityisen eri mieltä aiheesta.
Patternimätchäys (en tiiä mikä tää on oikeasti suomeksi)
Isohkompi ominaisuus jota itse olen toivonut kieleen jo vuosia on patternmätchäys. Optimistisesti ajatellen se saattaisi keritä C++26:een, mutta 29 on valitettavasti realistisempi vaihtoehto. Joskus vuonna 2019 naureskelin että kumpaanhan tämä ominaisuus tulee ensin, omaan lelukieleen vai C++:aan ja en ole aivan varma mitä ajattelen asiasta tällä hetkellä.
Joka tapauksessa, pienistä maanjäristyksistä huolimatta, iso osa keskiviikosta kului tämän parissa. Äänestyksissä positiivisena puolena tuli että 43 äänestäjää oli ominaisuuden jatkokehittämisen puolesta, 0 neutraalia ja 0 vastaan. Nyt lähinnä tarvittaisiin kesän tapaamiseen ajantasainen implementaatio ominaisuudesta kääntäjään että sillä olisi toivoa ehtiä C++26:een. Sain autettua tämän kanssa sen verran että kaivoin 4-5 vuotta vanhan clang-implementaation naftaliinista ja rebasetin sen uusimpaan päähaaraan miitin aikana.
Numeriikkatarinoita
Numeriikkaryhmä kokoontui koko tiistain ja puolet perjantaista. Isoimpana juttuna siellä puolella on yksikkökirjasto standardiin. Tämä tähtää vasta C++29:ään, joten sen hiomiseen on hyvä aika jäljellä. Implementaatio joka seuraa nykyistä esitystä löytyy täältä. Tyyppijärjestelmän käyttö yksikkötarkastuksiin ja -muunnoksiin on hemmetin hyvä tapa vähentää bugeja ja tehdä koodista uskomattoman paljon luettavampaa ilman että ajonaikainen suorituskyky laskee, ja on valitettavan vähän käytössä Suomen C++-maailmassa. Hyvän yksikkökirjaston tekeminen ei myöskään ole aivan triviaali homma, ja sellaisten käyttö on hyödyllistä laajasti sekä teollisuudessa että akatemisessa maailmassa, joten tämä olisi hyvä lisä standardikirjastoon.
SG6:ssa tarkoitus olisi saada ehdotukseen jonkinlainen tasapaino aikaiseksi käyttäjäystävällisyyden, matemaattisen tarkkuuden ja C++:n ominaisuuksien välille. Nykyinen ehdotus on aika tuhti matemaattisesti, joten käyttökokemuksien haku kirjastolle on tällä hetkellä aika korkealla prioriteetillä. Jos käytätte linkitettyä kirjastoa niin kannattaa antaa palautetta suoraan githubin keskusteluihin.
Numeriikkahuoneessa käsiteltiin myös käyttäjien määrittelemien tyyppien toimintaa std::simd
:in kanssa,
mietittiin atomäärisiä liukuluku min/max-funktioita ja
rajoitettuja numerojoukkoja ja
yritettiin päästä eroon ongelmallisista pyöristysmoodeista.
Muita mielenkiintoisia ehdotuksia
EWG:ssä tuli vastaan myös muita mielenkiintoisia ehdotuksia joihin en ollut etukäteen hirveän tarkkaan tutustunut.
Näistä Trivially relocate ja Replacement functions jäivät
parhaiten mieleeni. Ensimmäinen vastaa nähdäkseni hyvin pitkälle Rustin move
-operaatiota ja jälkimmäinen antaa
mahdollisuuden antaa uusi nimi ilmaisuille (aliasoida expressioneita näin finglishiksi).