Неправильно ли определять ключевые слова-макросы, если они улучшают читабельность кода?
Например, IMPLICIT
макрос:
#define IMPLICIT /* IMPLICIT constructor(parameters...); */
struct X
{
explicit X();
IMPLICIT X(int i);
IMPLICIT X(std::sting s);
explicit X(const char* ch);
};
Вместо:
struct X
{
explicit X();
X(int i);
X(std::sting s);
explicit X(const char* ch);
};
РАССМОТРЕНИЕ: Независимо от читабельности кода, определение IMPLICIT
макрос может быть изменен так, чтобы просто отключить все неявные конструкторы или …, для поддержки в будущем.
РЕДАКТИРОВАТЬ: Мой пример не важен, мой вопрос не относится к нему, и я удалил block
пример макроса.
Определение ключевых словоподобных макросов только для улучшения читабельности кода
Я думаю, что это приемлемо. Но, как сказал Марко, это довольно субъективно.
Я думаю, что примером макроса, улучшающего читабельность, является C ++ и NOTHROW
, Как ни странно, указав throw()
означает, что функция не выбрасывает; и против throw (SomeException)
, что означает, что функция может выдать исключение. Нет ничего интуитивного в объявлении чего-либо throw()
когда не бросает.
Много болтовни об этом на переполнении стека:
void func() throw(type)
?Microsoft определяет IN
, OUT
а также INOUT
чтобы помочь с удобочитаемостью и удобством использования. Макросы украшают параметры функции и ничего не определяют. Например, вы можете увидеть (у меня нет конкретного примера Microsoft под рукой):
// Process foo. Reuse baz if possible; reallocate if needed and return size.
// Return TRUE/FALSE as success/failure. Return an error code if result is FALSE.
int FooBarBaz(IN char* foo, IN int flen, INOUT char** baz, INOUT int* blen, OUT int* err);
Связанный: макросы полезны для абстрактного различия платформ. Например, экспорт функции из общего объекта (Unix и подделки) или динамических библиотек (Windows).
Связанный: макросы полезны для абстрактных различий в конфигурации. Например, значение или реализация ASSERT
в конфигурации отладки и выпуска.
Связанный: угон ключевых слов может быть полезным. Например, переопределение C ++ protected
а также private
в public
может быть полезен во время тестирования, поэтому тестовый пример может быть написан для методов, которые обычно недоступны.
Как уже говорилось, ваши макросы не улучшают читабельность. Кто-то может быть интересно, что BLOCK
или же IMPLICIT
означает, думая, что они выполняют какую-то особую функцию, тогда как на самом деле они этого не делают. Кажется, лучше подходит для комментариев или рефакторинга. В таких средах разработки, как Visual Studio, у вас есть возможность складывать строки кода (скрывать / показывать их) или группировать их в блоки документации (т.е. #REGION
). Макросы, которые ничего не делают, просто добавляют шум вашему коду.
Мой лучший макрос — это макрос регистрации:
#define SYSTEM_FAILURE(code, comment) \
{ \
System_Failure(code, comment, __FILE__, __FUNCTION__, __LINE__); \
}
Макрос — это самый простой способ добавить имя файла, имя функции и номер строки, где произошла ошибка.
Кроме этого макроса, в нашем магазине их нет.
Трудно найти хорошие примеры, где нельзя избежать макросов, которые используются для улучшения читабельности.
Это лучший пример, который я мог бы придумать (из ядра Linux):
#define FIELD_SIZEOF(t, f) (sizeof(((t*)0)->f))
Пример:
struct book {
char title[100];
char author[100];
};
// ...
printf("%lu\n", FIELD_SIZEOF(struct book, title)); // prints 100
(Я не знаю, можно ли избежать этого макроса в C ++.)
Кроме того, я думаю, что макросы иногда могут улучшить читабельность, когда они используются для генерации кода, чтобы исключить шаблонный код.