Как обеспечить соблюдение только одного определения?

Учитывая проект C, который должен поддерживать несколько сред, как мне использовать препроцессор, чтобы обеспечить определение только одной среды?

Я уже умею:

    #if defined PROJA
    (blah blah blah)
    #elif defined PROJB
    (etc)
    #else
    #error "No project defined"
    #endif

Однако все, что он делает, это говорит мне, определено ли 0 проектов. Если какая-то полезная душа определяет и проект A, и проект B, препроцессор примет только проект A. Однако правильное поведение, с моей точки зрения, — пометить ошибку.

Конечно, если определены только два проекта, эта проблема тривиальна. Как мне решить это с 200?


person JXG    schedule 10.06.2009    source источник
comment
с 200 хак препроцессора было бы очень сложно поддерживать, тогда вам скорее нужно, чтобы makesystem позаботилась об этом   -  person Joakim Elofsson    schedule 10.06.2009


Ответы (6)


Может есть разные файлы

include_proja.h
include_projc.h

а затем используйте свой Makefile или что-то еще, чтобы включить правильный файл. Затем вы можете сгенерировать 200 различных файлов с кодом и включить нужные во время компиляции.

Для таких вещей системы сборки и нужны. Если вы делаете что-то странное с макросами... найдите лучший способ вне исходного кода.

Каждый файл может сделать (извините за многословие здесь)

#define A_PROJECT_INCLUDE_WAS_INCLUDED

А потом сделай

#ifndef A_PROJECT_INCLUDE_WAS_INCLUDED
    #error "No project include"
#endif

Но некоторые пропущенные символы все равно сломают его, по всей вероятности.

Удачи

person Aiden Bell    schedule 10.06.2009
comment
Именно для таких вещей и существуют системы сборки. Если вы делаете что-то странное с макросами... найдите лучший способ вне исходного кода. Вы совершенно правы. - person JXG; 27.10.2009

что-то вроде этого:

#if defined PROJA
  #ifdef HAVE_PROJ
    #error 
  #endif

  #define HAVE_PROJ
#endif

#if defined PROJB
  #ifdef HAVE_PROJ
    #error 
  #endif

  #define HAVE_PROJ
#endif

#ifndef HAVE_PROJ
  #error No project selected (you need to define PROJA, PROJB, or ...)
#endif
person Shay Erlichmen    schedule 10.06.2009
comment
Я думаю, что это быстро станет мрачным, и на самом деле это не то, что следует делать в макросах, имхо. - person Aiden Bell; 10.06.2009

Попробуй это

#define ENV_UNKNOWN 0
#define ENV_MACOSX  1
#define ENV_LINUX   2
#define ENV_WIN32   3
/* and so on */


#ifndef ENVIRONMENT
/* no environment given, default to something (perhaps) */
#define ENVIRONMENT ENV_UNKNOWN
#endif

/* and now the environment specific parts */
#if (ENVIRONMENT == ENV_MACOSX)
#include "macosx_port.h"
#endif

#if (ENVIRONMENT == ENV_LINUX)
#include "linux_port.h"
#endif

#if (ENVIRONMENT == ENV_WIN32)
#include "win32_port.h"
#endif

#if (ENVIRONMENT == ENV_UNKNOWN)
#error You have to specify the ENVIRONMENT.
#endif

Теперь вы можете указать среду, для которой хотите скомпилировать, в командной строке, например:

cc -DENVIRONMENT=2 ...

Другой способ - включить/связать разные модули из вашей системы сборки в зависимости от среды, для которой вы компилируете.

person Markus Schnell    schedule 10.06.2009

Проблема с вложенными ifs заключается в том, что вы получите n ^ 2 разных тестов для n проектов.

Вам просто нужно какое-то выражение, которое в этом случае даст ошибку времени компиляции. Возможно:

#ifdef PROJA
#define PROJA-TEST "
#else
#define PROJA-TEST ""
#endif

и так далее для B, C и т.д.

Потом:

const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST " "More than one project is defined!";

РЕДАКТИРОВАТЬ: ... конечно, это проверяет только то, что определено нечетное количество проектов. Но это должно работать:

#ifdef PROJA
#define PROJA-TEST (
#endif

и так далее, то

const char *test_only_one_project = PROJA-TEST PROJB-TEST PROJC-TEST "More than one project is defined!" );
person Jacob B    schedule 10.06.2009
comment
Моей первой мыслью было: да, я бы тоже так поступил. Мой второй вопрос был таким: «Так вот почему никто больше не любит C?» - person Jeff Mc; 10.06.2009
comment
Точно. Препроцессор чертовски злой. - person Jacob B; 10.06.2009

возможно, вы можете сделать что-то вроде:

#if PROJ==A
(blah blah blah)
#elif PROJ==B
(etc)
#else
#error "No project defined"
#endif
person hiena    schedule 10.06.2009

person    schedule
comment
Это коротко и просто. Тем не менее, это кажется мне каким-то хакерским. - person Brian; 10.06.2009
comment
Пока какой-нибудь полезный кооператив, выполняющий ремонтные работы, не подумает: «Эй, эта переменная больше не используется… - person David; 18.05.2010