Более безопасная условная компиляция? - PullRequest
1 голос
/ 18 февраля 2011

В программе MSVC C ++ у меня есть часть кода, которую я хочу включить или отключить в зависимости от определения препроцессора

// 1.h
#ifdef MYOPTION
//...
#endif

Но я считаю, что это довольно опасно, когда он используется в файле .h, включенном в несколько модулей компиляции, поскольку я могу легко получить непоследовательные заголовки (я не хочу определять MYOPTION глобально, так как это потребует полная перекомпиляция каждый раз, когда я меняю ее):

// 1.cpp
#define MYOPTION
#include "1.h"

// 2.cpp
#include "1.h"

Конечно, это намного сложнее, чем этот упрощенный пример, из-за включения цепочечного заголовка.

Есть ли способ избежать такого несоответствия, например, ли ошибка времени компиляции без особых усилий?

Я думал о том, чтобы сделать #define MYOPTION 0 или 1, но тогда мне пришлось бы написать что-то вроде

#if MYOPTION == 1
//...
#elif !defined(MYOPTION)
#error ...
#endif

что выглядит слишком сложно ... Может быть, есть лучший вариант?

Ответы [ 4 ]

2 голосов
/ 19 февраля 2011

Примерно так: 1.h определите фиктивный раздел в объекте с различными параметрами.Таким образом, если MYOPTION когда-либо используется непоследовательно, компоновщик выдаст предупреждение.

1.h:

#ifdef MYOPTION
#pragma section("MYOPTION_GUARD",write)
#else
#pragma section("MYOPTION_GUARD",read)
#endif

namespace { __declspec(allocate("MYOPTION_GUARD")) int MYOPTION_guard; }

Компиляция с MYOPTION, определенной в a.cpp, но не в b.cppвыдает это предупреждение компоновщика (с помощью VC 2008):

b.obj : warning LNK4078: multiple 'MYOPTION_GUARD' sections found with different attributes (40300040)

Согласованное определение вообще не выдает предупреждений компоновщика.

1 голос
/ 18 февраля 2011

Думаю, вы сами перечислили большинство решений. Я бы использовал последнее решение, но, возможно, в несколько ином виде:

#ifndef MYOPTION
#error ...
#endif

...

#if MYOPTION == 1
//...
#endif

Потому что часто этот #if MYOPTION == 1 будет появляться более одного раза в каждом файле. Также ясно, что MYOPTION является реквизитом для этого файла.

Вы говорите, что это "выглядит слишком сложно", но я боюсь, что, вероятно, не существует такого менее "сложного" решения, чем это.

0 голосов
/ 18 февраля 2011

Возможно, вам нужно создать отдельную конфигурацию.

Вы можете перейти к Build -> Configuration Manager и создать новую конфигурацию (отдельно от DEBUG, RELEASE).Создание новой конфигурации позволит вам определить символы препроцессора, специфичные для этой конфигурации.

Например, с новой конфигурацией под названием «MyOption 1» вы можете добавить определение препроцессора MYOPTION = 1.То же самое касается MYOPTION = 2, 3, ...

Каждая конфигурация должна быть построена отдельно.DEBUG и RELEASE являются примерами отдельных конфигураций;DEBUG определяет _DEBUG, а RELEASE определяет NDEBUG

0 голосов
/ 18 февраля 2011

Предполагая, что вам действительно нужно использовать определения, лучше определить их через командную строку компилятора, чем #define в ваших исходных файлах. Затем процесс configure script / makefile / build устанавливает определение один раз, и вы гарантируете, что оно будет правильно согласовано для всех исходных файлов.

...