Научите магии макросов
От: Muxa  
Дата: 20.06.15 20:18
Оценка:
Есть куча строк вида

"SectionA0.SectionB0.ParamX"
"SectionA0.SectionB0.ParamY"
"SectionA0.SectionB1.ParamZ"
"SectionA1.SectionB2.SectionC0.ParamW"
...

Вложенность секций произвольная, в разумных пределах 2-3-4.

Эти строки используются в коде:
SomeFunctionCall("SectionA0.SectionB0.ParamX");

Хочется загнать их в константы:
namespace SectionA0 {
    namespace SectionB0 {
        static const char* ParamX = "SectionA0.SectionB0.ParamX";
        static const char* ParamY = "SectionA0.SectionB0.ParamY";
    }
    namespace SectionB1 {
        static const char* ParamZ = "SectionA0.SectionB1.ParamZ";
    }
}
namespace SectionA1 {
    namespace SectionB2 {
        namespace SectionC0 {
            static const char* ParamW = "SectionA1.SectionB2.SectionC0.ParamW";
        }
    }
}
...

чтобы в результате использовать константы как:
    SomeFunctionCall(SectionA0::SectionB0::ParamX);


Так как имена секций используются много раз, есть вероятность ошибки копипасты.
Поэтому решил применить магию макросов:
BEGIN_SECTION(SectionA0)
    BEGIN_SECTION(SectionB0)
        ENTRY(ParamX)
        ENTRY(ParamY)
    END_SECTION
    BEGIN_SECTION(SectionB1)
        ENTRY(ParamZ)
    END_SECTION
END_SECTION
BEGIN_SECTION(SectionA1)
    BEGIN_SECTION(SectionB2)
        BEGIN_SECTION(SectionC0)
            ENTRY(ParamW)
        END_SECTION
    END_SECTION
END_SECTION
...


В общем, даже не знаю как вопрос гуглу задать чтобы такие макросы накастовать.
Единственное что нарыл http://jhnet.co.uk/articles/cpp_magic
Сижу изучаю, может что и получится.
Любые советы приветствуются.
Re: Научите магии макросов
От: -n1l-  
Дата: 20.06.15 20:39
Оценка:
Ненадо макросами, лучше константами.
Re[2]: Научите магии макросов
От: Muxa  
Дата: 20.06.15 20:49
Оценка:
N>Ненадо макросами, лучше константами.
Видимо неясно объяснил.
Я и хочу при помощи макросов объявить константы.
То есть макросы
BEGIN_SECTION(Section)
    ENTRY(Param)

должены развернуться во что-то типа
namespace Section {
    static const char* Param = "Section" "." "Param"
Отредактировано 20.06.2015 21:25 Muxa . Предыдущая версия . Еще …
Отредактировано 20.06.2015 21:24 Muxa . Предыдущая версия .
Re: Научите магии макросов
От: watchmaker  
Дата: 21.06.15 00:13
Оценка: 8 (2)
Здравствуйте, Muxa, Вы писали:


M>В общем, даже не знаю как вопрос гуглу задать чтобы такие макросы накастовать.

M>Любые советы приветствуются.
Спроси как добавить внешнюю кодогенерацию к твоей системе сборки Пусть какой-нибудь внешний препроцессор (например, в виде программы на python) этот текст обработает и выдаст код на С++.

Впрочем можно обойтись и стандартными средствами языка.
Сначала пишешь нечто вроде этого:
#include <array>

template<size_t... Is> struct seq{};
template<size_t N, size_t... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...>{};
template<size_t... Is>
struct gen_seq<0, Is...> : seq<Is...>{};

template<size_t N1, size_t... I1, size_t N2, size_t... I2>
constexpr std::array<char const, N1+N2> concat(const std::array<char const, N1> &a1, char const (&a2)[N2], seq<I1...>, seq<I2...>){
    return {{ a1[I1]..., '.', a2[I2]... }};
}

template<size_t N1, size_t N2>
constexpr std::array<char const, N1+N2> concat(const std::array<char const, N1> &a1, char const (&a2)[N2]){
    return concat(a1, a2, gen_seq<N1-1>{}, gen_seq<N2>{});
}

static constexpr const std::array<char const, 1> current_section_name{{0}};

#define BEGIN_SECTION(section_name) namespace section_name { \
    static constexpr const auto parent_section_name = current_section_name; \
    static constexpr const auto current_section_name = concat(parent_section_name, #section_name); \

#define ENTRY(name)  \
    static constexpr auto name##_storage = concat(current_section_name, #name); \
    static constexpr const char* name = &name##_storage[1]; 

#define END_SECTION }


Потом записываешь своё описание:
BEGIN_SECTION(SectionA0)
    BEGIN_SECTION(SectionB0)
        ENTRY(ParamX)
        ENTRY(ParamY)
    END_SECTION
    BEGIN_SECTION(SectionB1)
        ENTRY(ParamZ)
    END_SECTION
END_SECTION
BEGIN_SECTION(SectionA1)
    BEGIN_SECTION(SectionB2)
        BEGIN_SECTION(SectionC0)
            ENTRY(ParamW)
        END_SECTION
    END_SECTION
END_SECTION


И используешь:
#include <stdio.h>
int main() {
    puts(SectionA0::SectionB0::ParamX);
    puts(SectionA1::SectionB2::SectionC0::ParamW);
    return 0;
}


В конце можешь убедится, что после компиляции в коде программы остаются только нужные строки.
Re: Научите магии макросов
От: Mazay Россия  
Дата: 21.06.15 05:38
Оценка:
Здравствуйте, Muxa, Вы писали:


M>Любые советы приветствуются.


+1 за кодогенерацию. Хоть на питоне, хоть на АВК-е. Макросы здесь точно не к месту.
Главное гармония ...
Re: Научите магии макросов
От: BulatZiganshin  
Дата: 21.06.15 10:32
Оценка:
Здравствуйте, Muxa, Вы писали:

магия макросов — чёрная магия
Люди, я люблю вас! Будьте бдительны!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.