blog.michalt.pl

Kilka słów o modułach w C++20, ale niestety tylko teoretycznie

08.05.2019 22:58 - Tech

W najbliższym czasie zamierzam skrobnąć kilka wpisów poświęconych tematyce języka C++. Dziś chciałbym poruszyć temat modułów które miały znaleźć się już w standardzie 17. Chciałbym uprzedzić, że nie jestem pewien co do tego czy przedstawione tu fragmenty kodu będą zgodne z finalną wersją standardu. Dlaczego tylko teoretycznie? Ponieważ to jedna z bardzo istotnych nowości którą niestety nie udało mi się przetestować z powodu braku wsparcia kompilatorów.

Przejdźmy do konkretów. Nowe rozwiązanie ma na celu między innymi rozwiązanie problemu wpływania na siebie kodu między nagłówkami. Moduły w przeciwieństwie do nagłówków będą bardziej hermetyczne. W teorii mają one być również rozwiązaniem bardziej optymalnym w procesie kompilacji – kompilator nie będzie zaglądał do pliku modułu wielokrotnie tak jak to miało miejsce w przypadku nagłówków. Co istotne, nagłówki będzie można używać nadal obok modułów.


Spróbujmy zatem pobawić się w teoretyków i stworzyć nasz moduł w C++:

plik cat.cpp:

module;
#include <iostream>
export module Cat;exportclass Cat {
public:
void meow() {
std::cout << "meow! meow! meow!";
}
};

class Dog {
public:
void bark() {
std::cout << "Wooff! Wooff! Wooff!";
}
};
export int getMeowString(int meowTimes) {
std::string meow = "";
while(meow-- > 0)
meow += "meow! ";

return meow;
}

W pierwszej linijce naszego kodu informujemy kompilator o tym, że ma do czynienia z modułem, w trzeciej zaś definiujemy jego nazwę – czyli w tym przypadku „Cat”.Powinniśmy jednak zwrócić uwagę na pewien istotny fakt. Część jego zawartości nie musi być dostępna na zewnątrz. Zwróć uwagę na słówko export w czwartej i szesnastej linijce kodu. W pierwszym przypadku wyeksportowana zostaje cała klasa z jej zasobami, w drugim zaś funkcja getMeowString(). Jak zapewne się domyślasz, w kodzie korzystającym z tego modułu nie będzie można skorzystać z klasy Dog, ale sama klasa Cat może korzystać z obiektów jej instancji lub innych zasobów które nie zostałyby wyeksportowane.

Jak zaimportować moduł? Bardzo prosto:

plik main.cpp

import Cat;
#include <iostream>
int main() {
Cat cat;
cat.meow();
std::cout << makeMeowString(5);
}

Tu nie trzeba tak naprawdę wiele tłumaczyć. Za import odpowiedzialna jest pierwsza linijka kodu. W dalszych, wewnątrz funkcji main korzystamy z udostępnionych zasobów.


Warto wspomnieć o tym, że kompilatory Clang i GCC częściowo już obsługują standard 20 i w niedalekiej przyszłości może również pojawić się obsługa modułów. Teoretycznie we wcześniej wspomnianym wariancie kompilatora GCC istnieje możliwość włączenia ich obsługi poprzez dodanie argumentu -fmodules-ts. Podobnie sprawy się mają w przypadku Clanga który wymaga podania argumentu -fmodules. Ponadto tryb kompilacji eksperymentalnie wspieranego standardu, w obu kompilatorach można włączyć dodając flagę -std=c++2a.


Czuję spory niedosyt ponieważ nie udało mi się skompilować kodu z modułami. Z pewnością wrócę jeszcze do tego tematu i w niedalekiej przyszłości opiszę kilka innych nowości ze standardu 20.