2011-02-07 24 views
5

Czy można zrobić coś takiego:zależny makro makro

#define F(x) \ 
    #ifdef DOUBLE \ 
     2*x \ 
    #else \ 
     x \ 
    #endif 

tak, że gdy używam F, co rozszerza się zależy od tego czy makro DOUBLE jest zdefiniowana? Nie sądzę, ale mam nadzieję. Ekspansje GNU są w porządku.

Edit W odpowiedzi na niektóre z odpowiedzi, jestem naprawdę używając tego zrobić kilka generacji kodu, gdzie kod jest nieco inny w zależności od tego, gdzie zostanie ona zdefiniowana. Z powodu kolejności, w jakiej są zawarte niektóre pliki i gdzie należy zdefiniować odpowiednie makra, przełączanie w ten sposób wymaga trochę faktoringu. Być może będę musiał to zrobić, ale byłbym zachwycony, gdybym nie musiał odciąć się od tego kąta!

Odpowiedz

8

Jeśli możemy ograniczyć ten problem, można tego dokonać. W szczególności, jeśli można zagwarantować, że DOUBLE jest albo

  • niezdefiniowane jako makro lub
  • jest zdefiniowany jako makro, które rozszerza się do pustego tokena sekwencji (np #define DOUBLE)

następnie można posłużyć się metodą pośrednią z tokena konkatenacji: przykład

#define F_IMPL_(x)  DOUBLE_IS_DEFINED 
#define F_IMPL_DOUBLE(x) DOUBLE_NOT_DEFINED 

#define F_1(x, m) F_2(x, m) 
#define F_2(x, m) F_IMPL_ ## m (x) 

#define F(x) F_1(x, DOUBLE) 

Zastosowanie:

F(t) 
#define DOUBLE 
F(t) 

wynik po wyprzedzającym:

DOUBLE_NOT_DEFINED 
DOUBLE_IS_DEFINED 

to podejście również działać w przypadku DOUBLE (jeśli istnieje) jest zdefiniowana jako makro, która rozciąga się w jednym znanym zasadzie, jeśli znacznik może stanowić część identyfikator (np. TRUE lub 1). Aby sobie z tym poradzić, wystarczy zmienić nazwę makra F_IMPL_ na F_IMPL_{TOKEN} (np. F_IMPL_TRUE lub F_IMPL_1).

+0

To jest idealne. –

+0

Dobra robota. Nie chciałbym jednak tego utrzymywać. – AShelly

13

Co z

#ifdef DOUBLE 
    #define F(x) (2 * (x)) 
#else 
    #define F(x) (x) 
#endif 
4

Dlaczego nie gniazdowania na odwrót?

#ifdef DOUBLE 
#define F(x) (2*(x)) 
#else 
#define F(x) (x) 
#endif 
3

Nie. Najbliższą rzeczą, którą można zrobić, jest umieszczenie tego w pliku nagłówkowym i # uwzględnienie tego pliku nagłówkowego za każdym razem, gdy zmieniają się definicje, na których zależy. Jest to czasami nazywane wzorem "X", ponieważ X jest używane jako makro zmieniające definicję.

Na przykład, jedno wspólne korzystanie z tego wzoru jest autogenerować nazwy ciągów wartości ENUM:

// File myenum_values.h 
// NOTE: _no_ header guards so we can include this file multiple times 
X(Apple) 
X(Orange) 
X(banana) 

// File myenum.h 
enum Fruit 
{ 
#define X(x) x, 
#include "myenum_values.h" 
} 

const char *FruitNames[] = 
{ 
#undef X 
#define X(x) #x, 
#include "myenum_values.h" 
}; 

// We now have an array of fruit names without having to define the enum twice