Я хочу определить макрос внутри другого макроса, чтобы избежать повторного написания.
В настоящее время мне нужно написать это:
MyClass : public Base<MyClass> {
Value<std::string> testString = value<std::string>(&MyClass::testString, "something");
// many more values like this
}
И я хочу написать что-то вроде этого, чтобы уменьшить беспорядок из вышеизложенного:
BASE(MyClass) {
VALUE(std::string, testString, "something");
}
Моим решением было бы определить два макроса стиля функции и BASE и VALUE, а внутри BASE определить еще одну константу с именем __CURRENT_CLASS, которая будет использоваться для всех вызовов VALUE. Но как мне определить эту константу в макросе BASE?
Вам также следует пройти несколько занятий по клавиатуре, чтобы улучшить скорость набора текста. Разработка программного обеспечения предполагает много ввода текста (не только кода, но и комментариев и документации).
Существуют приложения, которые могут использовать UML или блок-схемы и генерировать на их основе код. Мой короткий путь — использовать трафаретные файлы, и я даже написал собственный генератор кода. Не помогает при отладке или исправлении проблем.
@ThomasMatthews Ваш комментарий о клавиатуре высокомерен. Вы понятия не имеете о навыках набора текста ОП. Разработка программного обеспечения в первую очередь требует много размышлений, и это то, что они практикуют.
В показанном вами коде вы не определяете макрос внутри макроса (что невозможно). Вы даже не используете макрос внутри макроса. Все, что вы делаете, это расширяете два разных макроса по отдельности, без каких-либо связей или знаний друг о друге. Вы даже не расширяете VALUE как аргумент макроса BASE. Так что думать особо не о чем. За исключением того, что использование макросов таким образом, хотя и не является редкостью, имеет тенденцию усложнять понимание и поддержку кода и рано или поздно превращаться в беспорядок.
Кроме того, #undef имена ваших макросов #define перед ними, чтобы исключить возможные конфликтующие макросы из заголовков.
__CURRENT_CLASS — зарезервированный идентификатор.
Моей первой мыслью было: «Почему макросы? Почему бы не использовать шаблоны с переменным числом вариантов?».
@DYZ Да, возможно, я стал высокомерным после того, как пошел на курсы клавиатуры, чтобы улучшить скорость набора текста. Использование функций или подпрограмм, чтобы мне не приходилось повторять код. Да, я нахожу эти #define ll long long и другие заявления ужасающими. Годы рекомендаций по кодированию и обзоров кода, в которых отвергаются макросы синонимов и сокращений, которые затрудняют понимание или чтение кода. Тратить бесчисленные часы на отладку из-за неисправных макросов. Макросы — это зло. Печатание — важный навык для разработчиков программного обеспечения, дизайнеров, архитекторов и документаторов.
@Brainiac синтаксис, который вам нужен для макросов, невозможен, в основном из-за завершающего { после BASE(MyClass). Если вы переместили { внутрь BASE(), то он сможет определять дополнительных членов класса. В любом случае, что именно value<std::string>(&MyClass::testString, ...) должен делать? Почему вы передаете указатель на Value, который все еще создается? Как на самом деле выглядит Value?
Это похоже на проблему XY с ошибочной попыткой сохранить некоторые нажатия клавиш, что делает вопрос вдвойне плохо мотивированным.
Странные ответы здесь сосредоточены на моих навыках набора текста, а не на том факте, что иногда имеет смысл разгруппировать повторяющиеся строки с всегда одним и тем же содержанием с помощью простого текста, который действительно улучшает читаемость. Изображение, имеющее сотни этих строк значений, видеть сквозь них намного проще, если они упорядоченно структурированы.
@Brainiac - Если у вас так много переменных-членов, что вы устали вводить их все, это проблема, которую вы должны попытаться решить. Не скрывая код, а уменьшая классы.
«иногда имеет смысл разгруппировать повторяющиеся строки», мы не можем сказать, потому что вы не описали реальную проблему. Это настолько маловероятно и редко, что кажется более вероятным, что вы делаете это неправильно, поэтому мы спрашиваем вас, в чем настоящая проблема.





Синтаксис не совсем тот же, но вы можете определить псевдоним типа, чтобы имя класса всегда было одним и тем же.
Невозможно определить макрос внутри макроса. Альтернатива, используемая, когда макросы очень сложны, состоит в том, чтобы #define указать некоторые параметры, которые будут использоваться, а затем #include заголовочный файл, содержащий определения макросов. Затем параметры можно переопределить и снова включить заголовок.
#include <string>
template <typename T> class Base {};
template <typename T> struct Value {};
template <typename T, typename Container>
Value<T> value(Value<T> Container::*, const T&);
#define BASE(name) \
class name: public Base<name> { \
using ThisClass = name;
#define ENDBASE(name) }
#define VALUE(name, type, init) \
Value<type> name = value<type>(&ThisClass::name, init)
BASE(MyClass)
VALUE(testString, std::string, "something");
ENDBASE(MyClass);
Но зачем тебе это делать???
Спасибо. Я решил это, не используя напрямую ваш подход, а вместо этого включил typedef в базовый класс, а не в макрос, который решил проблему.
@PasserBy Я использую его для того, чтобы, во-первых, сэкономить себе немного времени на написании сотен строк «Value<type> name = ...», а во-вторых, это значительно улучшает читаемость.
@TrentP - Не тот, кто отрицает, но это просто ужасно. Мы не должны говорить людям, как писать отвратительный код. Даже если они об этом просят. И, видимо, настоящая проблема в том, что существуют сотни переменных-членов. Вот проблема, которую надо решить!
— Зачем вымещать на мне свое неодобрение? потому что в результате получается ужасный код, независимо от того, как все началось.
Если вы хотите избежать повторного ввода, приобретите утилиту нажатия клавиш, которая позволяет вам писать кучу текста одним нажатием клавиши. Или сделать реальные функции.
typedefиusing— хорошие способы создания синонимов (при использовании шаблонов, массивов или других структур данных). Макросы — это зло.