Опитвам се да разреша проблем, при който имам няколко декларации на разпръснати променливи (в една единица за компилиране) и искам да изградя вектор от техните адреси по време на компилация (ако не е възможно като пространствено ефективен вектор, други структури от данни също ще работи, като например свързан списък).
static type var1;
static type var2;
static type var3;
// ...
for (type *i : varlist)
do something with each varX
Като разширен пример и обосновка, приемете, че имам скриптов език и имам начин да модифицирам скриптови променливи от C++, като получа манипулатор, да речем scriptvar *
. Тези манипулатори могат да бъдат намерени чрез извикване на функция get_var
с име:
scriptvar *var1 = get_var ("namespace::var1");
scriptvar *var2 = get_var ("namespace::var2");
Това е бавно, така че искам да кеширам стойностите scriptvar *
в глобалните променливи. За съжаление, трябва да извикам get_var
само след инициализиране на скриптовия език, което може да се случи късно в програмата, така че не мога просто да използвам get_var
в израз на инициализатор, но трябва да забавя извикването му.
Би било хубаво, ако мога да напиша клас scriptvarwrapper
или да използвам някакво друго средство, което би ми позволило да декларирам тези глобални манипулиращи променливи във всяка точка, но също така да изградя пространствено ефективен вектор на тези променливи по време на компилиране, до който мога да получа достъп по-късно:
struct scriptvarwrapper
{
scriptvar *handle;
const char *name;
/ ...
};
static scriptvarwrapper var1 ("namespace::var1");
static scriptvarwrapper var2 ("namespace::var2");
static scriptvarwrapper var3 ("namespace::var3");
void init_vars ()
{
for (scriptvarwrapper *i : somecontainer)
i->handle = get_var (i->name);
}
Би било идеално, ако този контейнер в крайна сметка бъде просто масив/векторна структура от данни в паметта, която се състои от указателите към тези променливи. Очевидно целта е да се изгради това по време на компилация, така че решенията, поставящи нещо в std::vector
в конструктора, няма да решат проблема.
Актуализация:
За да изясня проблема - това, което искам, е решение, което автоматично компилира масив или списък от всички тези декларирани променливи по време на компилиране, без да се налага да ги изброявам поотделно и без конструктор да изгражда списък динамично по време на изпълнение, вероятно чрез някои готини и изящен метод за метапрограмиране, като функция constexpr, която по някакъв начин свързва всички тези променливи заедно в списък или, за предпочитане, нещо, което води само до масив от указатели към всички обекти на scriptvarwrapper в паметта, завършващи със специална стойност или с известен размер.
По-конкретно, ръчното поставяне на обектите scriptvarwrapper в статичен масив няма да свърши работа, нито поставянето им в std::vector в техния конструктор ще бъде достатъчно.
Обосновката за това е поддържаемостта - ако добавя променлива някъде в моята програма, не искам отново да я изброявам отделно, защото това е лесно да се забрави - и ефективността - не искам да изграждам динамична структура от данни по време на изпълнение за това, което всъщност е константа, известна по време на компилация.
Предпочитанието за някакъв вид масив се дължи на ефективността - решение, което води до структура от 100 байта за всеки такъв обект по време на компилация, разбира се, не е много полезно, по същия начин би било разпределяне на много голям масив само за бъдещо разширяване.
Актуализация 2:
За да поясним допълнително, точният синтаксис и оформление и тип на хранилището не са толкова важни. Това, което е важно, е, че мога да имам няколко независими и разпръснати във файла(овете) декларации на променливи и техните адреси се поставят автоматично и без ръчно изброяване в някакъв вид контейнер само за четене, който по някакъв начин може да бъде повторен на време за изпълнение, за да намерите всички тези декларации.
Целта е да намеря ефективно всички тези променливи без възможността да забравя да изброя една отделно, нито да трябва да изграждам структури от данни динамично по време на изпълнение, тъй като цялата информация е известна по време на компилиране, а C++ е толкова готин език с компилиране метапрограмиране на времето. Уви, не знам как и дали изобщо е възможно.
Актуализация 3:
Съжалявам за всички тези актуализации, научавам колко трудно е да изразя този проблем. Ето пример как биха могли да изглеждат нещата:
static scriptvarwrapper var1 ("name");
ADD_LIST (var1); // magic macro
static scriptvarwrapper var2 ("name");
ADD_LIST (var2);
Ключът тук е, че въпреки че трябва да изброя всяка променлива и дори да използвам грозен макрос може би, е трудно да пренебрегна или забравя да изброя променлива, защото ADD_LIST
е директно на мястото на декларацията - не забравяйте, че декларациите може да са разпръснати в дълъг файл или дори в някои включени файлове, така че търся решение, което прави трудно да забравя да включа декларация в моя списък.
Следователно в идеалния случай конструкторът или простото действие на деклариране на scriptvarwrapper
ще се увери, че е в списъка, така че да не може да бъде пренебрегнато. Решение, което поставя всичко в std::vector
в конструктора, ще работи, освен че ще се почувства грозно поради времето за изпълнение.
Като стар човек на C, обмислях да използвам GCC разширения, за да ги поставя в техния собствен ELF раздел, подобно на самите конструктори, които работят върху ELF системи - те се събират от указател в техен собствен раздел и всички такива секции са свързани във връзка време, със специален обектен файл в края, който доставя крайната стойност на сентинела.
std::map
може да свърши работа - person   schedule 18.04.2018