Есть куча строк вида
"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
Сижу изучаю, может что и получится.
Любые советы приветствуются.
N>Ненадо макросами, лучше константами.
Видимо неясно объяснил.
Я и хочу при помощи макросов объявить константы.
То есть макросы
BEGIN_SECTION(Section)
ENTRY(Param)
должены развернуться во что-то типа
namespace Section {
static const char* Param = "Section" "." "Param"
Здравствуйте, 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;
}
В конце можешь убедится, что
после компиляции в коде программы остаются только нужные строки.
Здравствуйте, Muxa, Вы писали:
магия макросов — чёрная магия