Я пытаюсь решить проблему, когда у меня есть несколько разрозненных объявлений переменных (в одной единице компиляции), и я хочу построить вектор их адресов во время компиляции (если это невозможно в качестве эффективного вектора пространства, другие структуры данных также будет работать, например, связанный список).
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