C++20

**C++20** on C++-ohjelmointikielen ISO-standardiversio ISO/IEC 14882:2020, jonka kehitys alkoi C++17-standardin valmistumisen jälkeen. Standardiversio äänestettiin valmiiksi 15. helmikuuta 2020 ja hyväksytyksi ISO:n äänestyksessä syyskuussa. Standardiversio on julkaistu joulukuussa 2020.
Edellinen standardiversio on ISO/IEC 14882:2017 C++17.
Seuraava kehitettävä versio tulee olemaan C++23.

## Kehityskohdat

Version kehityskohtia ovat muun muassa:
* moduulit
* rinnakkaisuuden jatkokehitys
** uusi synkronointikirjasto
** *latch* ja *barrier* luokat
* *[[#Concepts|concepts]]*
* *[[#Ranges|ranges]]*
* *[[#Coroutines|coroutines]]*
* lambda-operaattoreiden käytön rajoitteiden vähentäminen `decltype` -yhteydessä
** `[=, this]` -kaappaus
* kolmisuuntainen vertailu nk. avaruusalusoperaattorilla `<=>`
* `volatile`-tuen merkintä suurelta osin vanhentuneeksi
* `std::span`
* ominaisuustestimakroja esikääntäjälle
* bittioperaatioita
* `char8_t` lisäys, `char16_t` ja `char32_t` muutokset (`u"foo"` ja `U"foo"`) Unicode-tukeen
* vanhentuneeksi merkittyjen ominaisuuksien poistoja

Haskell-kielen tyyppinen konsepti-ominaisuus, *ranges*-kirjasto sekä `std::future` odotetaan olevan myös kehityskohteina.

Bjarne Stroustrup julkaisi työryhmälle paperin nimellä *Remember the Vasa!* viitaten Vasa-laivaan, jossa hän muistutti perusasioiden tärkeydestä ominaisuuksien määrän sijaan.

Stroustrup on sanonut C++20-standardista sen olevan ”kolmas merkittävä standardi” (kuudesta standardista), jossa merkittävä tarkoittaa sen ”muuttavan ihmisten ajattelutapaa”. Merkittäviksi kohdiksi mainitaan:
* *concepts*
* moduulit
* *coroutines*

Moduulien käyttö voi mahdollistaa esikääntäjästä luopumisen.

### Lykättyjä tai hylättyjä ominaisuuksia
* *contracts* on lykätty versioon C++23/C++26.
* verkko-ohjelmointituen laajennukset (ISO/IEC TS 19216:2018)
* reflektio
* transaktiomuistin tuki

Standardia on kuitenkin myös kritisoitu päätöksistä säilyttää yhteensopivuus ja haluttomuudesta rikkoa ABI-yhteensopivuus. ABI:n muutoksilla pyrittäisiin saavuttamaan parempaa suorituskykyä.

## std::format
Standardikirjaston lisäys `std::format` on uusi vaihtoehto merkkijonojen muotoiluun, jonka tavoitteena on tarjota sama joustavuus kuin `printf`-sarjan funktioilla.
Esimerkki:

```c++
string message = format("The answer is {}.", 42);
```


## Concepts
ISO:n tekninen määrittely: ISO/IEC TS 19217:2015
GCC-kääntäjän versiossa 6 on tukea ominaisuudelle.
Standardimallikirjasto sisältää ominaisuutta tukevia määrittelyitä.

*Concepts* on laajennus template-malleihin, jotka voivat toimia rajoitteina sallituille argumenteille tai parametreille.
*Constraint*-rajoitteella voidaan valita ylikuormitukset ja erikoistumiset. *Concepts* toimii nimettynä joukkona rajoitteita, jotka arvioidaan käännösaikana. Tavoitteena on semanttisen tarkistuksen lisääminen syntaksitarkistuksen lisänä.
Ominaisuuden on sanottu olevan puuttuva ominaisuus geneerisen ohjelmoinnin haittapuolien eliminoimiseksi.

Kielen nimettyjä vaatimuksia voidaan esittää Concepts-kirjaston avulla. Esimerkiksi `std::hash`-tuen vaatimuskonsepti `Hashable` voidaan ilmaista:

```c++
template<typename T>
concept Hashable = requires(T a) {
    { std::hash<T>{}(a) } -> std::convertible_to<std::size_t>;
};
```


## Ranges
Eric Nieblerin esimerkkitoteutus on julkaistu osana ehdotusta ominaisuuden lisäämiseksi C++ standardiin ja on myöhemmin hyväksytty standardiin `std::ranges`-kirjastoksi. 
Kirjasto rakentuu *Concepts*-kirjaston ominaisuuksille. 
Toteutus on *koottava* abstraktiokerros iteraattoreiden päällä.

Kirjasto tukee Haskell-kielen tapaan *laiskaa arviointia*, jossa ääretöntä määrää tukevasta toiminnosta suoritetaan vain tarvittava osa. 
Esimerkiksi kokonaislukujoukosta *[1, ..]* voidaan valita viisi numeroa ja tulostaa ne seuraavasti:

```c++
auto num = view::take(view::ints(1), 5);
    ranges::for_each(num, [](int i){ std::cout << i << " "; });
```


Esimerkki (`std::views` on lyhenne `std::ranges::views` nimiavaruudelle):

```c++
std::vector<int> ints{0,1,2,3,4,5};
    auto even = [](int i){ return 0 == i % 2; };
    auto square = [](int i) { return i * i; };

    for (int i : ints | std::views::filter(even) | std::views::transform(square)) {
        std::cout << i << ' ';
    }
```

.. joka tulostaa annettujen arvojen joukosta (0..5) parillisten numeroiden (0, 2, 4) neliöt seuraavasti:

```
0 4 16
```


## Coroutines
*Coroutines* on ylemmän tason kielien kuten Simulan ominaisuus, joka toimii vaihtoehtona aliohjelmille (alifunktioille): rutiinit ovat pinottomia. *Coroutines* on tarkoitettu tilanteisiin, jossa eri funktiot vaihtavat suoritusvuoroaan jatkaen aiemmasta tilasta. *Coroutines* sallii funktion suorittamisen pysäyttämisen ja jatkamisen ja lisää kolme uutta operaattoria:
* `co_await`, pysäyttää väliaikaisesti suorituksen palauttamatta arvoa kutsujalle
* `co_yield`, pysäyttää väliaikaisesti ja palauttaa arvon kutsujalle
* `co_return`, lopettaa suorituksen ja palauttaa arvon.

Uudet operaattorit mahdollistavat asynkronisen suorituksen, generaattorit ja *laiskat funktiot*.

Esimerkki:

```c++
generator<int> iota(int n = 0) {
  while(true)
    co_yield n++;
}
```


Boost-kirjastossa on esimerkkitoteutus C++:lle.
*Coroutines* on hyväksytty mukaan C++20:een.

## Moduulit
Moduulit (*modules*) on vaihtoehtoinen tapa otsikkotiedostoille, joka muun muassa mahdollistaa makrojen eriyttämisen. Aiemmin ohjelmoijille on ollut mahdollista käyttää kolmea nimettyä kapselointia: 
# muuttujanimi
# funktionimi
# luokkanimi

Moduulit lisäävät neljännen nimetyn kapseloinnin, joka sisältää kaikki kolme aikaisempaa yhdessä.
Moduulit on hyväksytty mukaan C++20:een.

Epävirallinen tuki toiminnolle on ollut aiemmin Clang-kääntäjässä.

Esimerkki:

```c++
// moduulissa:
// helloworld.cpp
export module helloworld;  // module declaration
import <iostream>;         // import declaration

export void hello() {      // export declaration
    std::cout << "Hello world!\n";
}

// moduulin käyttö:
// main.cpp
import helloworld;  // import declaration

int main() {
    hello();
}
```


## Lähteet

## Aiheesta muualla
* Standardivedokset