Вызов функции непосредственно перед основным - PullRequest
7 голосов
/ 07 марта 2011

Можно ли зарегистрировать функцию, которую нужно запустить немедленно до ввода main?Я знаю, что все глобальные объекты создаются до ввода main, поэтому я мог бы поместить код в конструктор глобального объекта, но это не гарантирует какого-либо конкретного порядка.Я хотел бы добавить регистрационный код в конструктор, но, увы, я не знаю, что там делать :) Полагаю, это сильно зависит от системы?

Ответы [ 4 ]

9 голосов
/ 07 марта 2011

Если вы используете gcc, вы можете использовать атрибут constructor в функции, чтобы он вызывался до main (см. Документацию для получения более подробной информации).1007 *

constructor

destructor

Атрибут constructor вызывает автоматический вызов функции до того, как выполнение входит в main ().Точно так же атрибут destructor заставляет функцию вызываться автоматически после завершения main () или вызова exit ().Функции с этими атрибутами полезны для инициализации данных, которые будут использоваться неявно во время выполнения программы.

2 голосов
/ 07 марта 2011

Не уверен, что это именно то, что вы хотите ... Но он должен делать эту работу.

int main() {
  static int foo = registerSomething();
}

Лучше явно вызывать такие функции регистрации, либо при основном, либо при первом доступе (но при первом доступе init могут возникнуть проблемы, если вы многопоточны).

1 голос
/ 07 марта 2011

Я предполагаю здесь, но:

  1. Вы хотите зарегистрировать что-то в другом модуле компиляции
  2. Вы столкнулись с проблемой при регистрации, потому что глобальные переменные, в которых вы 'Сохранение регистраций еще не было построено.

C ++ определяет, что статическая функция инициализируется за некоторое время до ее первого доступа, поэтому вы можете обойти ее, как показано ниже.

typedef std::map<std::string, std::string> RegistrationCache;

RegistrationCache& get_string_map()
{
    static RegistrationCache cache;
    return cache;
}

class Registration
{
    Registration(std::string name, std::string value)
    {
        get_string_map()[name] = value;
    }
};
0 голосов
/ 12 июля 2013

Цель

Допустим, вы хотите следующее:

STATIC_EXECUTE {
  printf("This probably prints first"\n");
}

STATIC_EXECUTE {
  printf("But order isn't guaranteed in the language spec, IIRC"\n");
}

int main(int argc, char **argv) {
  printf("This definitely prints last. Buh Bye.\n");
}

Реализация

Версия C ++ - статическая переменная + конструктор:

// This is some crazy magic that produces __StaticExecute__247
// Vanilla interpolation of __StaticExecute__##__LINE__ would produce __StaticExecute____LINE__
// I still can't figure out why it works, but it has to do with macro resolution ordering
// If you already have Boost, you can omit this part
#define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
#define BOOST_PP_CAT_I(a, b) BOOST_PP_CAT_II(~, a ## b)
#define BOOST_PP_CAT_II(p, res) res

// This avoids repeating the BOOST_PP_CAT 5X
#define STATIC_EXECUTE \
  STATIC_EXECUTE_I(BOOST_PP_CAT(__StaticExecute__, __LINE__))

// This is the meat, a static instance of a class whose constructor runs your code
#define STATIC_EXECUTE_I(uniq_name)               \
static struct uniq_name {                         \
  uniq_name();                                    \
} BOOST_PP_CAT(uniq_name, __var);                 \
uniq_name::uniq_name()  // followed by { ... }

C версия - статическая переменная + функция

// ... 

// The meat: a static variable initialized from a function call
#define STATIC_EXECUTE_I(uniq_name)            \
static void uniq_name ();                      \
static int BOOST_PP_CAT(uniq_name, __var) =    \
  (uniq_name(), 0);                            \
static void uniq_name()                        // followed by { ... }

Примечания

  • ИМХОВерсия C ++ немного элегантнее.Теоретически он занимает немного меньше места.В противном случае, potato, po-tat-oh.

  • Предостережение: Я не проверял версию "C" на подходящем компиляторе только для C.Скрещенные пальцы;опубликовать заметку, если она не работает.

  • Предостережение: переносимость компилятора в общем сложная вещь.Я не был бы шокирован, если есть ошибка в каком-то другом компиляторе.

  • Код BOOST_PP_CAT украден из boost / preprocessor / cat.hpp .Я упростил реализацию, и в процессе может скомпрометировать переносимость.Если это не работает, попробуйте оригинальную (более детальную) реализацию и оставьте комментарий ниже.Или, если вы уже используете Boost, вы можете просто использовать их версию.

  • Если вы пытаетесь понять магию Boost, учтите это (по крайней мере для меня и в этом сценарии)), похоже, также работает следующее:

    #define BOOST_PP_CAT(a, b) BOOST_PP_CAT_I(a, b)
    #define BOOST_PP_CAT_I(a, b) a ## b
...