2010-10-19 18 views
10

Desidero scrivere una libreria da utilizzare, è necessario includere solo un file di intestazione. Tuttavia, se hai più file sorgente e includi l'intestazione in entrambi, otterrai più errori di definizione, poiché la libreria è dichiarata e definita nell'intestazione. Ho visto le librerie di sola intestazione, in Boost, penso. Come hanno fatto?Librerie di intestazione e errori di definizione multipli

+0

stai usando guardie incluse? EDIT: dai un'occhiata a Sams rispondi allo – smerlin

+0

@smerlin: dai un'occhiata alla risposta di sams. – GManNickG

risposta

21

dichiarare le funzioni inline, e metterli in uno spazio dei nomi in modo che non si scontrano:

namespace fancy_schmancy 
{ 
    inline void my_fn() 
    { 
    // magic happens 
    } 
}; 
+0

Ma, si consiglia di rendere ** tutte ** le funzioni 'in linea? Indipendentemente dalla loro natura? Pensavo che solo le funzioni "corte" dovessero essere "in linea". – Arun

+5

Ignora i tuoi professori. Non scrivono codice per vivere. "Solo le funzioni brevi dovrebbero essere sottolineate" è una regola generale, ma ci sono così tante eccezioni e tanti altri motivi più importanti per cui dovresti o dovresti * non * incorporare una funzione in modo da rendere quasi inutile la regola del pollice. –

+0

"La micro-ottimizzazione precoce è la radice di tutti i mali" essendo la prima ragione per non essere in linea che viene in mente. –

2

Boost utilizza solo intestazioni librerie molto perché come lo STL, è per lo più costruito utilizzando i modelli con classe e funzionalità , che sono quasi sempre solo header.

Se non si scrivono i modelli, eviterò di includere il codice nei file di intestazione: è più un problema che non ne vale la pena. Rendi questa una semplice libreria statica.

0

Ci sono molte librerie Boost solo per intestazione, ma tendono ad essere molto semplici (e/o solo modelli). Le librerie più grandi ottengono lo stesso effetto attraverso alcuni trucchi: hanno "link automatico" (vedrai questo termine usato here). Essenzialmente hanno un gruppo di direttive per il preprocessore nelle intestazioni che individuano il file lib appropriato per la piattaforma e usano un #pragma per indicare al linker di collegarlo. Quindi non è necessario collegarlo esplicitamente, ma è ancora in corso linked.

+0

Come si usa la cosa di collegamento automatico in g ++? So che in MSVC++ puoi usare '#pragma (lib," blah.lib ")' ma come fai a fare lo stesso con g ++? – Epro

+0

@Epro: ho paura di non sapere come è fatto. Potrebbe essere necessario guardare la fonte di spinta. – rmeador

5

Il motivo principale per cui Boost è in gran parte solo di intestazione è perché è fortemente orientato ai modelli. I modelli generalmente ottengono un passaggio dalla regola di una definizione. Infatti, per utilizzare efficacemente i modelli, è necessario che la definizione sia visibile in qualsiasi unità di traduzione che utilizza il modello.

Un altro modo per aggirare l'unica regola di definizione (ODR) è utilizzare le funzioni inline. In realtà, ottenere un free-pass dall'ODR è ciò che fa davvero lo inline - il fatto che potrebbe inline la funzione è davvero più un effetto collaterale opzionale.

Un'ultima opzione (ma probabilmente non altrettanto valida) è rendere statiche le tue funzioni. Questo può portare a un codice gonfio se il linker non è in grado di capire che tutte quelle istanze di funzione sono davvero le stesse. Ma lo cito per completezza. Si noti che i compilatori spesso integrano le funzioni static anche se non sono contrassegnati come inline.

+0

Bene, i documenti Boost cita la natura di sola intestazione di gran parte della libreria come caratteristica. Ed è solo la roba che non può essere ragionevolmente intestazione (ad esempio la regexp stuff ha dipendenze OS) che non è solo intestazione. Pertanto, mentre alcune librerie secondarie sono indubbiamente intestazione solo perché sono codice di modello, è sbagliato attribuire tale motivazione a Boost nel suo insieme, almeno secondo i documenti. –

Problemi correlati