-
Notifications
You must be signed in to change notification settings - Fork 12
Description
C++ proposal implementation cpp-ru/ideas#622
Partial implementation of STEELMAN's requirement:
2C. Syntactic Extensions. The user shall not be able to modify the source language syntax. In particular the user shall not be able to introduce new precedence rules or to define new syntactic forms.
Макросы препроцессора являются важной частью С++ и попытка отказаться от них, например для поддержки С++ модулей, приведет к нарушению обратной совместимости со старым кодом и нарушит многие способы (опции) компиляции файлов (Translation Unit), которые используются десятилетиями различными инструментами и утилитами.
Однако стандартный режим использования макросов (препроцессорных определений) не совместим с новой концепции С++ модулей, так как их исходный код становится зависим от внешних не контролируемых факторов (макросов), причем детектирование подобных источников проблем может быть очень затруднено.
Данное предложение для правил использования макросов препроцессора при компиляции С++ модулей направлено на обеспечение полной обратной совместимости со старым, ранее разработанным исходным кодом и новым кодом, с учетом особенностей С++ модулей.
Предложение состоит в следующем:
- Вводится два режима обработки макросов компилятором:
- Легаси режим - для всех файлов, кроме файлов модулей.
- Новый режим - только для файлов модулей.
- В новом режиме добавляются области видимости (время жизни) макросов
- В файле С++ модуля вводятся ограничения на применение макросов в экспортируемых именах переменных, функций и классов
Различия между двумя режимами заключается в следующем. Легаси режим обработки макросов применяется для всех файлов, кроме файлов C++ модулей (т.е. обработка макросов происходит как и раньше - только на уровне препроцессора, тогда как новый режим обработки макросов предназначен исключительно для С++ модулей, а сама обработка макросов идет с учетом AST.
Области видимости (время жизни) макроса в модуле
Макросы в глобальном фрагменте С++ модуля
Определение и использование макросов в глобальном фрагменте модуля (т.е. после ключевого слова module; и до начала его реализации, определяются и используются в соответствии со старым (легаси) режимом обработки без каких либо ограничений.
Макросы после определения С++ модуля
Макроопределения в разделе реализации модуля (т.е. после ключевого слова export module name; и до конца файла), имеют время жизни (область видимости) только до конца текущего модуля. При включении модуля в другой файл(модуль), макроопредения из раздела реализации модуля не видны за его пределами, но доступны внутри импортируемых модулей.
module;
// Глобальное макроопределение, доступно в любом месте до его явного удаления #undef MACRO_GLOBAL
#define MACRO_GLOBAL macro_global
export module name;
// Локальное макроопределение, доступно только до конца модуля и внутри импортируемых модулей
#define MACRO_LOCAL macro_local
import mod; // В модуле mod видны оба макроса MACRO_GLOBAL и MACRO_LOCAL
// В конце файла автоматическое удаление макроса модуля,
// что равносильно указанию #undef MACRO_LOCALОграничения на использование (раскрытие) макросов в модуле
Макроопределения в модулях не могут быть использованы в операторах экспорта модуля и любых публичных методах экспортируемых классов:
module mod;
#define MACRO macro_name
void MACRO() { // раскрытие макроса внутри реализации модуля
std::cout << "MACRO!\n";
}
export void MACRO(); // ERROR раскрытие макроса в экспортируемой функции
export void macro_name(); // ok
class cls_internal {
public:
cls_internal() = default;
void MACRO(); // ok - класс является локальным для модуля
};
export class cls_external {
public:
cls_external() = default;
void MACRO(); // ERROR - макрос используется в публичном методе экспортируемого класса
protected:
void MACRO(); // ?? - макрос используется в защищенном методе (поведение можно настраивать опцией компилятора)
private:
void MACRO(); // ok - макрос используется в приватном методе экспортируемого класса
};
// В конце файла автоматическое удаление макроса модуля,
// что равносильно указанию #undef MACRO_LOCAL