Newsgroup: it.comp.lang.c++
Titolo: Namespace vs #define macro e #typedef

Salve a tutti,
non ho trovato nulla googlando, così chiedo a voi:
In uno progetto che ho ereditato, ho avuto bisogno di inserire un file
header e, per evitare diverse collisioni di nomi strutture e altro,
pensavo di relegarlo all'interno di un namespace ad-hoc. Però in
questo file vengono definite diverse macro del preprocessore, alcuni
typedef ed enum (oltre a classiche struct).
Come si comportano le macro del preprocessore sotto un namespace?
Dalle prove che ho fatto mi sembra che non vengono influenzate (mi da
una errore di macro già definita).
Per i typedef e gli enum invece?
Grazie.

 Per i typedef e gli enum invece?
Per loro invece i namespace esistono.
Per esempio, compilando il seguente programma ottieni vari errori di 
compilazione:
namespace abc {
    #define meno -
    typedef int intero;
    enum enumerato { primo, secondo, terzo };
};
int main()
{
    intero a = 3 meno 1;
    enumerato x = secondo;
}
Puoi eliminare tutti gli errori se sostituisci il corpo del main con il 
seguente codice:
    abc::intero a = 3 meno 1;
    abc::enumerato x = abc::secondo;
Nota che l'espressione "3 abc::meno 1" sarebbe illegale.
Nota anche che se non avessi definito la macro "meno", l'espressione "3 
meno 1" sarebbe illegale.
-- 
Carlo Milanesi
http://digilander.libero.it/carlmila

 esistono.
Come supponevo...
...quindi la mia soluzione di inserire i vari header all'interno di
namespace diversi è improponibile per i #define macro!
Avete qualche consiglio per "isolare" questi header (5/6 file), senza
modificarli (o ridurre al massimo le modifiche)? Tenendo conto che
questi .h, provenendo da un progetto in C sono pieni di #define (che
non posso modificare).
Un esempio di due file header (ridotti per comodità, in realtà sono
molto più lunghi e "complessi"):
<primo.h>
#define CONST_PIPPO 1
#define CONST_PLUTO (CONST_PIPPO + 1)
#define CONST_PAPERINO 4
enum ENUM1 {
  ENUM1_1,
  ENUM1_2,
  ENUM1_3,
};
typedef struct _STR_1 {
  int A;
  char B;
  long C;
} STR_1;
</primo.h>
<secondo.h>
#define CONST_PIPPO 2
#define CONST_PLUTO (CONST_PIPPO + 1)
#define CONST_PAPERINO 10
#define CONST_TOPOLINO 11
enum ENUM1 {
  ENUM1_1,
  ENUM1_2,
  ENUM1_3,
  ENUM1_4_NUOVO,
  ENUM1_5_ NUOVO,
};
typedef struct _STR_1 {
  int A;
  char B;
  long C;
} STR_1;
</secondo.h>
E' un po che ci sto pensando ma non ho alcuna idea!
Escluderei la soluzione (veramente brutta) di preporre ad ogni #define
x una #ifdef x #undef x.
Essendo abbastanza indipendenti dal resto del progetto, pensavo di
realizzare diverse librerie (una per ognuno di questi header) che
implementano una classe wrapper che eredita da una base comune, ma
vedo già alcuni problemi:
- diverse librerie da gestire
- classe base comune a più librerie
Qualcuno ha già affrontato un problema simile e può darmi qualche
idea?
Grazie.
Mirko

 non posso modificare).
Il principale motivo per cui sono stati inventati i namespace e' proprio 
risolvere il conflitto di nomi che sia ha quando in uno stesso file si 
usano due librerie che definiscono lo stesso simbolo.
Vedo due soluzioni, entrambe le quali richiedono la modifica del file 
header.
1) Se tutte le macro sono di fatto delle costanti, sostituirlo degli 
enum o con variabili const, e includere tutto il file in un namespace.
2) Decorare tutte le definizioni e istanziazioni di macro con un 
prefisso o suffisso univoco. Per esempio, sostituire la seguente riga:
#define CONST_PIPPO 1
con la seguente
#define LIB1_CONST_PIPPO 1


 #define LIB1_CONST_PIPPO 1
Giustissimo. Se poi c'è un brutto clash di nomi da risolvere,
esiste anche #undef MACRO.
Per esempio:
header1.hh -> #define pi 3.14
file1.cc -> int nome_con_pi_dentro;
Qui per evitare rogne con "pi" come parte di nome di variabile, si
userà #undef pi prima della dichiarazione.
In genere però questi sono usi piuttosto rari.
Matteo

 user� #undef pi prima della dichiarazione.
Temi che
	nome_con_pi_dentro
diventi
	nome_con_3.14_dento
?
Non credo che il preprocessore faccia le sostituzioni in maniera cos� 
"bovina"... il nome da sostituire deve comunque essere un identificatore 
completo.
E.