Newsgroup: it.comp.lang.c++
Titolo: funzione template come parametro di template

Salve,
come da subject, avevo pensato di usare una funzione templatizzata da 
passare come parametro ad una classe template, ma il linker si lamenta 
che non ne trova l'implementazione.
Posto qui una parte del codice:
<code>
//----------------------------------------------------------------------------
template <typename T, void fz_clear(T*, size_t sz), size_t tsize = 
sizeof(T) >
class P_SimpleFreePacketClear
{
   public:
     P_SimpleFreePacketClear() : FreeList(tsize) {}
     ~P_SimpleFreePacketClear() {}
     T* get();
     void release(T* f);
   private:
     P_freeList FreeList;
};
//----------------------------------------------------------------------------
struct P_packet
{
   TCHAR name[_MAX_PATH];
};
//----------------------------------------------------------------------------
#if 1
//----------------------------------------------------------------------------
inline void fz_clearFirstChar(P_packet* p, size_t sz)
{
   p->name[0] = 0;
}
//----------------------------------------------------------------------------
typedef P_SimpleFreePacketClear<P_packet, fz_clearFirstChar > 
freeListPacket;
//----------------------------------------------------------------------------
#else
//----------------------------------------------------------------------------
template <typename T>
void fz_clearFirstChar(T* p, size_t sz)
{
   p->name[0] = 0;
}
//----------------------------------------------------------------------------
typedef P_SimpleFreePacketClear<P_packet, fz_clearFirstChar<P_packet> > 
freeListPacket;
//----------------------------------------------------------------------------
#endif
</code>
ho rimediato usando una funzione inline non templatizzata (#if 1 -> ok, 
#else -> errore linker).
Mi piacerebbe sapere se sbaglio qualcosa o è un comportamento normale.
Grazie dell'attenzione
Saluti

 Posto qui una parte del codice:
Non riscontro errori nel tuo codice, ma per riuscire a compilarlo ho dovuto
modificarne alcune parti, giacché non conosco la definizione di alcuni
tipi.
In generale, fornire frammenti non autonomi di codice non è una buona idea.
E' sempre meglio creare esempi ad-hoc, brevi, completi e indipendenti, che
consentano di riprodurre il problema. Nel caso in questione, non dovrebbe
essere difficile.
Max

Max M. ha scritto:

ok, scusa, hai ragione :-)
comunque, dopo aver preparato l'esempio minimale ho visto che in questo 
modo funziona, quindi non è un problema di codice :-(
allora ho visto che il problema deriva dall'usare la classe in due 
librerie che poi vengono linkate al programma principale.
Ho provato a mettere un oggetto ed il richiamo alla get() in un sorgente 
del progetto principale e funge anche con la funzione templatizzata.
Quindi la funzione viene implementata solo se si trova nel codice 
principale.
riposto, giusto per completezza, il codice minimo funzionante:
//----------------------------------------------------------------------------
template <typename T, void fz_clear(T*, size_t sz), size_t tsize = 
sizeof(T) >
class P_SimpleFreePacketClear
{
   public:
     P_SimpleFreePacketClear()  {}
     ~P_SimpleFreePacketClear() {}
     T* get()
     {
       T* buff = (T*) new char[tsize];
       fz_clear(buff, tsize);
       return buff;
     }
     void release(T* f) { delete [](char*)f; }
   private:
};
//----------------------------------------------------------------------------
struct P_packet
{
   TCHAR name[_MAX_PATH];
};
//----------------------------------------------------------------------------
#if 0
//----------------------------------------------------------------------------
inline void fz_clearFirstChar(P_packet* p, size_t sz)
{
   p->name[0] = 0;
}
//----------------------------------------------------------------------------
typedef P_SimpleFreePacketClear<P_packet, fz_clearFirstChar > 
freeListPacket;
//----------------------------------------------------------------------------
#else
//----------------------------------------------------------------------------
template <typename T>
void fz_clearFirstChar(T* p, size_t sz)
{
    p->name[0] = 0;
}
//----------------------------------------------------------------------------
typedef P_SimpleFreePacketClear<P_packet, fz_clearFirstChar<P_packet> > 
freeListPacket;
//----------------------------------------------------------------------------
#endif
//----------------------------------------------------------------------------
int main()
{
   freeListPacket packSet;
   P_packet* packet = packSet.get();
   _tcscpy(packet->name, _T("dummy"));
   packSet.release(packet);
   return EXIT_SUCCESS;
}
//----------------------------------------------------------------------------

 passare come parametro ad una classe template, ma il linker si lamenta
[...]
Questo mi ricorda la tecnica, basata sui template, descritta nel
libro
"Modern C++ Design" di Andrei Alexandrescu: policy based design.
E' molto potente ed è descritta molto bene. L'ho usata più volte
con successo nei miei progetti.
Sul suo sito, puoi scaricare gratuitamente il capitolo sulla policy
based design e anche quello sugli smart pointers, implementati
con questa tecnica.
Il sito di Alexandrescu: 
http://erdani.org
Ciao Ugo

 Grazie dell'attenzione
#include <iostream>
template<class T>
void Function(T* t) {
  std::cout << t << std::endl ;
}
template<class T, void (*F)(T*)>
class Class {
public:
  void callFunction(T* t) {
    F(t) ;
  }
} ;
int main()
{
  Class<char, Function> Obj ;
  Obj.callFunction("hello") ;
}