Общие тонкости программирования на C ++ - PullRequest
2 голосов
/ 08 апреля 2011

Проблема, с которой я столкнулся, проиллюстрирована в следующем коде.

#include <iostream>

#define X 4

int main()
{

    std::cout << "should be 4: " << X << std::endl;
#define Y X + 4
    std::cout << "should be 8: " << Y << std::endl;

#undef Y
#define Y X+0
#undef X
#define X Y+1

    std::cout << "expecting 5: " << X << std::endl;
}

Ошибка:

test2.cc: In function ‘int main()’:
test2.cc:17: error: ‘X’ was not declared in this scope

Шаблон, который я пытаюсь эмулировать, расширяет программу при коде / сборкеуровень (очень похоже на то, как модули nginx подключены во время компиляции ).Мне нужно создать расширяемую структуру времени компиляции, которая является расширяемой (подключаемой) путем добавления #include s в мою сборку, что приводит к вектору boost-mpl с уникальным именем, содержащим все мои плагины.Поэтому, если X является уникальным конечным именем, X_0, X_1, X_2 являются именами, которые создаются по пути, поскольку к вектору применяется mpl-вектор push_back.

I ЗНАЮ абстракции boost :: препроцессора являются ключевыми, но я пока не хочу выделять время на его изучение, так как я создаю прототип той части системы, котораяв конечном итоге будет модульным во время компиляции.

Итак, для дальнейшего использования,

  1. Почему я получаю ошибку выше?
  2. Как должен выглядеть правильный необработанный шаблон препроцессора.
  3. Как выглядит правильный шаблон boost-preprocessor-library.

Ответы [ 3 ]

5 голосов
/ 08 апреля 2011

компиляция с g ++ -E дает следующее:

int main()
{

    std::cout << "should be 4: " << 4 << std::endl;

    std::cout << "should be 8: " << 4 + 4 << std::endl;






    std::cout << "expecting 5: " << X+0 +1 << std::endl;
}

Таким образом, вы можете понять, почему вы получаете ошибку.

4 голосов
/ 08 апреля 2011

Почему бы не убить двух зайцев одним выстрелом и не использовать пространства имен.

// a.hpp:

namespace a {
    const int module_id = 0;

    class module_a : extension_module< module_id > { … };
}

#undef last_module
#define last_module a

// b.hpp:

namespace b {
    const int last = last_module::module_id + 1;

    class module_b : extension_module< module_id > { … };
}

#undef last_module
#define last_module b

Это гораздо менее "умно" и оставляет след идентификаторов.

Однако модули должны включаться в один и тот же порядок каждый раз, чтобы ODR работал.

Я не сторонник убийства птиц.

2 голосов
/ 08 апреля 2011

Проблема вашего примера кода в том, что у вас есть циклическая зависимость в макросах X и Y:

Y определяется как X + 0, а X определяется как Y + 1. Поэтому, когда макросы раскрываются (это происходит в том месте, где вы используете X), у вас возникает проблема.

ADD:

Кажется, что поведение таково: при развертывании макроса X внутри его определения имя X не определяется в пространстве имен препроцессора, поэтому вы видите X + 0 + 1 как расширение X.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...