- Припомняне
- Стандартни модули
- Модулите във Visual Studio 2019
- Експортирани и неекспортирани модули
- Повече информация
- Какво следва?
В предишната си тема ви дадох малко информация за това какво представляват модулите в C++20. В тази тема ще видим как ще ги използваме. Преди да започна темата, нека припомним докъде стигнахме.
Припомняне
Създадох модул с името amxxbg, който имаше модуларен интерфейсен агрегат и модуларен имплементиращ агрегат, както и main.cpp, който се води потребител и който използваше тези два агрегата. Тук са трите сорс файла:
Модуларен интерфейсен агрегат:
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
export auto print() -> void;
Код за потвърждение: Избери целия код
// amxxbg1.cpp
module amxxbg1;
auto print() -> void{
std::cout << "amxx-bg.info/forum" << std::endl;
}
Код за потвърждение: Избери целия код
// main1.cpp
import amxxbg1;
auto main() {
print();
return 0;
}
Стандартни модули
Съществено, нито модуларняит интерфейсен агрегат, нито модуларняит имплементиращ агрегат се променят в модула amxxbg1.
Модуларен интерфейсен агрегат:
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
export auto print() -> void;
Код за потвърждение: Избери целия код
// amxxbg1.cpp
module amxxbg1;
auto print() -> void{
std::cout << "amxx-bg.info/forum" << std::endl;
}
Код за потвърждение: Избери целия код
// main1.cpp
import std.core;
import amxxbg1;
auto main() {
print();
return 0;
}
Използването на хедърният файл iostreamе възможно, разбира се, усещам и накъде отиват работите - кои модули са достъпни? Ето какво видях от поста на Microsoft "Using C++ Modules in Visual Studio 2017" в team блога им.
- std.regex - Съдържа всичко от хедърният файл <regex>
- std.filesystem - Съдържа всичко от хедърният файл <experimental/filesystem>
- std.memory - Съдържа всичко от хедърният файл <memory>
- std.regex - Съдържа всичко от хедърният файл <regex>
- std.threading - Съдържа всичко от хедърните файлове <atomic>, <condition_variable>, <future>, <mutex>, <shared_mutex>, <thread>
- std.core - Съдържа всичко от останалата част на стандартната библиотека
Експортирани и неекспортирани модули
Нека към сегашният ни модул да добавим малко повечко методи и да видим къде идва разликата.
Модуларен интерфейсен агрегат:
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
auto addition(int, int) -> int;
export auto multiplication(int, int) -> int;
export auto print() -> void;
Модуларният интерфейсен агрегат съдържа декларациите на експортираният модул: export module amxxbg1; Модулната декларация започва с така наречената модулна компетентност/сфера/област. Само имена след модулната компетентност/сфера/област, които са декларирани с ключовата дума export са експортирани. Ако не са, името не е видимо извън модула и следователно има връзка с модула. Това, в този пример, е конкретно за addition, но не важи за функциите multiplication и print.
Модуларен имплементиращ агрегат:
Код за потвърждение: Избери целия код
// amxxbg1.cpp
import std.core;
module amxxbg1;
auto addition(int a, int b) -> int {
return a + b;
}
auto multiplication(int a, int b) -> int {
return a * b;
}
auto print() -> void {
printf("amxx-bg.info/forum");
}
Основната програма:
Код за потвърждение: Избери целия код
// main1.cpp
// #include <iostream> // (1)
// #include <numeric> // (1)
// #include <string> // (1)
// #include <vector> // (1)
import std.core; // (2)
import amxxbg1;
auto main() -> int {
std::cout << std::endl;
// std::cout << "Addition of 1000 and 15 = " << addition(1000, 15) << std::endl;
std::vector<int> numbers = { 1, 2, 3, 4, 5, 6, 7 , 8, 9, 10 };
auto result = std::accumulate(numbers.begin(), numbers.end(), 1, multiplication);
std::cout << "std::accumulate(numbers.begin(), numbers.end(), multiplication) = " << result << std::endl;
print();
return 0;
}
Сега въпросът е, какво ще стане ако махнем коментара на този ред, където е извеждането и използването на функцията addition? Да си припомним, че addition не беше експортирана функция, следователно, ще има връзка само с модула.
Компилаторът се оплаква, че функцията addition е използвана в main програмата, без да е декларирана или по-конкретно, видима.
Повече информация
Първо, можете да експортирате по няколко начина:
- Всеки метод поотделно
- По групи
- Цял namespace
Ето пример как всеки метод поотделно се експортира. Това използвахме и досега.
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
auto addition(int, int) -> int;
export auto multiplication(int, int) -> int;
export auto print() -> void;
Освен всеки метод поотделно да го експортирате и да пишете някакви ключови думи всеки път на всеки метод, можете да направите и така:
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
auto addition(int, int) -> int;
export {
auto multiplication(int, int) -> int;
auto print() -> void;
}
Цял namespace
Третият вариант, и на мен който всякаш ми е най-удобен, цял namespace да бъде експортиран. Позволява максимално ниво на модуларност и разделение на кода в същото време, подреденост.
Код за потвърждение: Избери целия код
// amxxbg1.cppm
export module amxxbg1;
namespace amxxbg1 {
auto addition(int, int) -> int;
}
export namespace amxxbg1 {
auto multiplication(int, int) -> int;
auto print() -> void;
}
Ре-експортиране на модул
Понякога, искате да експортирате нещо, което сте импортирали от друг модул. Ако нямате експорт на импортираният модул, импортираният модул има последователно свързване с модула и имената му не са видими извън самият него. Ето един конкретен пример:
Видими срещу невидими
Представете си, че искам да импортирам и използвам модула amxxbg.core и amxxbg.core_new в нов модул amxxbg. Ето го модулните интерфейсни агрегати на amxxbg.core и amxxbg.core_new:
Код за потвърждение: Избери целия код
// модуларен интерфейсен агрегат amxxbg.core
export amxxbg.core;
export auto multiplication(int, int) -> int;
Код за потвърждение: Избери целия код
// модуларен интерфейсен агрегат amxxbg.core_new
export amxxbg.core_new
export auto addition(int, int) -> int;
Код за потвърждение: Избери целия код
// Модуларен интерфейсен агрегат на amxxbg
export module amxxbg;
import amxxbg.core; // не се ескпортира с multiplication
export import amxxbg.core_new; // експортира се с addition
multiplication(1000, 2); // всичко точно
addition(1000, 100); // тук също
Код за потвърждение: Избери целия код
// Модуларен имплементиращ агрегат на amxxbg
import amxxbg;
multiplication(1000, 2); // Грешка
addition(1000, 100); // тук също
Препакетирани модули
Има и по-удобен начин за представянето на подобни модули, както и да се избегне тази грешка отгоре. С пълна сила важат всички правила и начини за експортиране споменати по-горе. Ето един пример с групи:
Код за потвърждение: Избери целия код
export module amxxbg;
export{
import amxxbg.core;
import amxxbg.core_new;
import amxxbg.basics;
}
Какво следва?
За сега мисля да се поизчакат някои неща да се изчистят сред C++20 и ще се връщам назад към C++17, C++14 и C++11.