dernières remarques:
 
1) on peut manipuler mes UniqueLoader::Shared directement, en remplaçant la classe par un typedef et en faisant une fonction load(shread_ptr<Shared> )
 
2) quand y a pas beaucoup d'éléments ça va, la méthode benête des comparaisons fonctionnes, mais le cout est fonction de (N! / 2!) pour N>2 si je ne m'abuse. alors un joli DesignPattern Stratégie, une joli surcahrge de < et == (en utilisant les adresses), et à partir d'une certaine limite, on créer tous les UniqueLoader, on fout tout en conteneur, on trie, on parcours en fusionnant (affectation pour partager l'implémentation) les éléments égaux.  
l'algo à la con que j'ai filé, est bête et inefficace, (il doit y avoir plusieurs fois les meme comparaisons), mais il a le mérite de s'écrire facilement et l'invocation est simple (UniqueN(tuple)). ça serait interessant quand meme de voir si le compilo est pas capable de détecte les comparaisons en trop.
 
donc:
si y a beaucoup -> tri + affectation
sinon, la solution N² comme un tri par bulles: comparaison avec chaque élément, et si ==, on partage l'implémentation
 
le problème de ces solutions, c'est que l'allocation. il faut un truc genre tuple, bref un truc indexable et initialisable ( (obligatoirement, les reférences impose cela, à moins de fonctionner avec des adresses). avec un Array<N>, on peut std::sort, mais on ne peut pas initialiser (à moins de passer par des pointeurs), mais avec un Tuple, on doit passer par la méthode N² de comparaisons (pas d'itérations possibles). donc: soit passer à un fonctionnement avec des pointeurs directement, comme ça on peut faire un Array<UniqueLoader, N> et le remplir tranquillement, puis le std::sort ou N²; soit garder nos sympatiques tuples et garder la N².
 
le tout est donc de bien estimer les 3 méthodes: N!, N², et std::sort, en terme de cycle et de mémoire. N² me semble la plus appropriée, j'ai un peu peur de std::sort, à déterminer expérimentalement.