ciao oregon, ho provato a fare il natural merge sort passando le liste tramite puntatori, però nel metodo copia mi da un problema che non riesco a risolvere: ti posto solo la classe lista.h perchè le altre classi sono sempre le stesse.

lista.h
codice:
#include <iostream>
#include <stdlib.h>

using namespace std;

template<class posizione, class tipoelem>
class lista
{
   public:
      virtual void crealista() = 0;
      virtual bool listavuota() = 0;
      virtual posizione primolista() = 0;
      virtual bool finelista(posizione) = 0;
      virtual posizione succlista(posizione) = 0;
      virtual posizione predlista(posizione) = 0;
      virtual tipoelem leggilista(posizione) = 0;
      virtual void scrivilista(posizione, tipoelem) = 0;
      virtual void inslista(posizione, tipoelem) = 0;
      virtual void canclista(posizione) = 0;
      
      void stampalista();
      void fondiordinate(lista &, lista &);
      void epurazione();
      void naturalmergesort();
   private:
      void distribuisci(lista *, lista *);
      void copiacatena(posizione *, lista *, posizione *, lista *);
      void copia(posizione *, lista *, posizione *, lista *, bool *);
      void merge(lista *, lista *, lista *, int *);
      void fondicatena(posizione *, lista *, posizione *, lista *, posizione *, lista *);
      
};

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::stampalista()
{
   posizione p = primolista();
   while(!finelista(p))
   {
      cout << leggilista(p) << "\n";
      p = succlista(p);
   }
   cout << "\n";
}
   

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::fondiordinate(lista<posizione, tipoelem> &A, lista<posizione, tipoelem> &B)
{
   posizione pa = A.primolista();
   posizione pb = B.primolista();
   posizione pc = primolista();
   
   tipoelem elem1 = A.leggilista(pa);
   tipoelem elem2 = B.leggilista(pb);
   while(!A.finelista(pa) && !B.finelista(pb))
   {
      if(elem1 <= elem2)
      {
         inslista(pc, elem1);
         pa = A.succlista(pa);
      }
      else
      {
         inslista(pc, elem2);
         pb = B.succlista(pb);
      }
      elem1 = A.leggilista(pa);
      elem2 = B.leggilista(pb);
   }
   while(!A.finelista(pa))
   {
      inslista(pc, elem1);
      pa = A.succlista(pa);
      elem1 = A.leggilista(pa);
   }
   while(!B.finelista(pb))
   {
      inslista(pc, elem2);
      pb = B.succlista(pb);
      elem2 = B.leggilista(pb);
   }
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::epurazione()
{
   posizione p = primolista();
   posizione q;
   posizione t;
   while(!finelista(p))
   {
      q = succlista(p);
      while(!finelista(q))
      {
         if(leggilista(p) == leggilista(q))
         {
            t = succlista(q);
            canclista(q);
            q = t;
         }
         else
            q = succlista(q);
      }
      p = succlista(p);
   }
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::naturalmergesort()
{
   int numerocatene;
   lista<posizione, tipoelem> *A, *B, *L;
   do
   {
      A->crealista();
      B->crealista();
      distribuisci(A, B);
      numerocatene = 0;
      crealista();
      merge(A, B, L, &numerocatene);
   }while(numerocatene != 1);
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::distribuisci(lista<posizione, tipoelem> *A, lista<posizione, tipoelem> *B)
{
   posizione p = primolista();
   posizione pa = A->primolista();
   posizione pb = B->primolista();
   do
   {
      copiacatena(&p, this, &pa, A);
      if(!finelista(p))
         copiacatena(&p, this, &pb, B);
   }while(!finelista(p));
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::copiacatena(posizione *p, lista<posizione, tipoelem> *L, posizione *pa, lista<posizione, tipoelem> *A)
{
   bool finecatena = false;
   do
   {
        copia(&p, L, &pa, A, &finecatena); 
         while(!finecatena);
}
h
template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::copia(posizione *p, lista<posizione, tipoelem> *L, posizione *pa, lista<posizione, tipoelem> *A, bool *finecatena)
{
   tipoelem elemento = leggilista(p);
   A->inslista(pa, elemento);
   p = succlista(p);
   pa = succlista(pa);
   if(finelista(p))
      finecatena = true;
   else
      finecatena = (elemento > leggilista(p));
}

template<class posizione, class tipoelem>
void lista<posizione, tipoelem>::merge(lista<posizione, tipoelem> *A, lista<posizione, tipoelem> *B, lista<posizione, tipoelem> *L, int *numcatene)
{
   posizione p = primolista();
   posizione pa = A->primolista();
   posizione pb = B->primolista();
   
   while(!A->finelista(pa) && !B->finelista(pb))
   {
      fondicatena(&pa, A, &pb, B, &p, L);
      numcatene++;
   }
   while(!A->finelista(pa))
   {
      copiacatena(&pa, A, &p, L);
      numcatene++;
   }
   while(!B->finelista(pb))
   {
      copiacatena(&pb, B, &p, L);
      numcatene++;
   }
}
in pratica il problema è il seguente:
144 C:\Dev-Cpp\esercizi\Lista\lista.h no matching function for call to `lista<nodop<int>*, int>::copia(nodop<int>***, lista<nodop<int>*, int>*&, nodop<int>***, lista<nodop<int>*, int>*&, bool*)'

secondo me la chiamata del metodo corrisponde con il prototipo però mi dà errore. come mai?

PS: ho messo in rosso la riga dove mi dà l'errore.