Il C++ comprende, in teoria, la compilazione dei template su file .cpp, ma l'unico compilatore che conosco a supportare realmente questa feature è clang (LLVM). Per tutti gli altri, devi includere il codice del template con il file .h
Non esiste :-)Non un'alternativa "pulita" almeno... Con le classi normali si può fare benissimo, ma i template sono come le macro e non ci si può girare intorno più di tanto...
Si, ovviamente puoi fare una classe di interfaccia che contiene solo le API pubbliche, e a sua volta incapsula un puntatore ad una classe di implementazione privata (questo pattern si chiama Private Implementation, e si trova ad esempio nelle librerie Qt).
In sostanza, le API pubbliche possono includere il puntatore tramite banale forward reference, senza includere il relativo header. La parte in cpp ovviamente conterrà entrambi gli header (API pubblica + implementazione privata), e dal momento che potrai fornire solo il compilato, il suo codice rimane nascosto insieme alla definizione dell'implementazione privata.
Oltre che per nascondere l'implementazione, questo metodo è utile per switchare a runtime l'implementazione di alcune funzioni. Ad esempio ho usato nei miei engine questo metodo per poter cambiare al volo una implementazione con un'altra (per esempio sostituire un algoritmo con una versione approssimata più leggera a runtime in caso di degrado del framerate del gioco).
Un'altra tecnica è quella della composizione dei namespace. Ad esempio nelle API pubbliche metti solo determinate classi, mentre negli header privati della libreria includi ulteriori classi interne che non vuoi esporre all'esterno. Avrai così un'API pubblica che condivide lo stesso namespace, ma espone un numero inferiore di classi (ciascuna classe, però, deve essere identica nelle due versioni dell'header altrimenti ti compila codice non funzionante).
Questa seconda tecnica lavorando a compile time è più efficiente della prima, ma non ti consente di variare a runtime il comportamento della classe sostituendo la sua implementazione privata (ma non è detto che questa caratteristica sia utile nel tuo caso, è solo un appunto).
Credo ci siano altre 1-2 tecniche più complesse, che coinvolgono l'uso di una Factory di oggetti che istanzia a runtime oggetti di classi derivate e ti restituisce puntatori a classi astratte (quindi usa un header diverso nell'API pubblica, che contiene solo classi astratte, rispetto a quello usato nel .cpp), ma dipende tutto da cosa vuoi fare e a cosa ti serve.
typedef std::map<qualcosa,qualcosaDiComplicato> mioTipo;