Perché si dovrebbe usare #include_next in un progetto?

Per citare la documentazione di iOS sulle intestazioni Wrapper :

#include_next non distingue tra l’inclusione di e di “file”, né controlla che il file specificato abbia lo stesso nome del file corrente. Cerca semplicemente il nome del file, iniziando dalla directory nel percorso di ricerca dopo quella in cui è stato trovato il file corrente.

L’uso di “#include_next” può portare ad una grande confusione. Si consiglia di utilizzarlo solo quando non ci sono altre alternative. In particolare, non dovrebbe essere utilizzato nelle intestazioni appartenenti a un programma specifico; dovrebbe essere usato solo per fare correzioni globali lungo le linee di fixincludes.

Quindi, due domande, che cos’è #include_next e perché dovresti mai averne bisogno?

Viene utilizzato se si desidera sostituire un’intestazione predefinita con uno di propria creazione, ad esempio, supponiamo di voler sostituire “stdlib.h”. Dovresti creare un file chiamato stdlib.h nel tuo progetto e che verrebbe incluso al posto dell’intestazione predefinita.

#include_next è usato se vuoi aggiungere qualcosa a stdlib.h piuttosto che sostituirlo interamente. Si crea un nuovo file chiamato stdlib.h che contiene:

 #include_next "stdlib.h" int mystdlibfunc(); 

E il compilatore non includerà di nuovo il tuo stdlib.h in modo ricorsivo, come sarebbe il caso con un semplice #include, ma piuttosto continuerà in altre directory per un file chiamato “stdlib.h”.

È utile se stai supportando più versioni di qualcosa. Ad esempio, sto scrivendo un codice che supporta PostgreSQL 9.4 e 9.6. Esistono diverse modifiche API interne, principalmente nuovi argomenti per le funzioni esistenti.

Compatibilità intestazioni e funzioni wrapper

Potrei scrivere intestazioni di compatibilità con funzioni di wrapper in static inline con nuovi nomi per ogni cosa, fondamentalmente un’API wrapper, in cui utilizzo il nome del wrapper ovunque nel mio codice. Dì something_compat.h con:

 #include "something.h" static inline something* get_something_compat(int thingid, bool missing_ok) { assert(!missing_ok); return get_something(thingid); } 

ma è brutto sparpagliare _compat o qualsiasi suffisso ovunque.

Intestazione Wrapper

Invece, posso inserire un’intestazione di compatibilità nel percorso di inclusione quando si costruisce contro la versione precedente, ad esempio compat94/something.h :

  #include_next "something.h" #define get_something(thingid, missing_ok) \ ( \ assert(!missing_ok), \ get_something(thingid) \ ) 

quindi il resto del codice può semplicemente usare la firma 9.6. Quando si costruisce contro 9.4, -Icompat94 prefisso -Icompat94 al percorso di ricerca dell’intestazione.

È necessario prestare attenzione per evitare la valutazione multipla, ma se si utilizza #include_next è chiaro che non si mente affidandosi a gcc. In tal caso puoi anche usare espressioni di istruzioni .

Questo approccio è utile quando la nuova versione è il target “primario”, ma è richiesta la compatibilità con le versioni precedenti per una versione precedente per un periodo di tempo limitato. Quindi stai deprecando progressivamente le versioni precedenti e stai cercando di mantenere pulito il tuo codice con riferimento alla versione corrente.

alternative

Oppure sii una persona ragionevole, usa C ++ e usa funzioni sovraccaricate e funzioni inline template: p