ciao a tutti, ho creato la struttura dati insieme con una lista non ordinata. nel test dei metodi dell'insieme mi dà un errore nella struttura insiemel.h. posto i codici

insieme.h
codice:
#ifndef insieme_h
#define insieme_h

#include<iostream>
#include<stdlib.h>

using namespace std;

template<class tipoelem>
class insieme
{
   public:
      virtual void creainsieme() = 0;
      virtual bool insiemevuoto() = 0;
      virtual bool appartiene(tipoelem) = 0;
      virtual void inserisci(tipoelem) = 0;
      virtual void cancella(tipoelem) = 0;
      //virtual void unione(insieme<tipoelem> *, insieme<tipoelem> *) = 0;
      //virtual void intersezione(insieme<tipoelem> *, insieme<tipoelem> *) = 0;
      //virtual void differenza(insieme<tipoelem> *, insieme<tipoelem> *) = 0;
      
      void test();
};

#endif

template<class tipoelem>
void insieme<tipoelem>::test()
{
   cout << "                  ***test del metodo CREAINSIEME***\n\n";
   cout << "il metodo CREAINSIEME crea un insieme privo di elementi. per provare il metodo\n";
   cout << "basta utilizzare il metodo INSIEMEVUOTO.\n\n";
   cout << "   insiemevuoto() = " << this->insiemevuoto() << "\n\n";
   system("pause");
   system("cls");
   
   cout << "                  ***test del metodo INSIEMEVUOTO***\n\n";
   cout << "il metodo INSIEMEVUOTO testa se l'insieme e' privo o meno di elementi.\n\n";
   cout << "   test del metodo su insieme privo di elementi:\n";
   cout << "      insiemevuoto() = " << this->insiemevuoto() << "\n";
   cout << "   test del metodo su insieme con almeno un elemento:\n";
   cout << "      inserimento di un valore nell'insieme: a = ";
   tipoelem a;
   cin >> a;
   this->inserisci(a);
   cout << "      insiemevuoto() = " << this->insiemevuoto() << "\n\n";
   system("pause");
   system("cls");
   
   cout << "                  ***test del metodo APPARTIENE***\n\n";
   cout << "il metodo APPARTIENE testa se il valore fornito come argomento e' presente\n";
   cout << "o meno tra i valori dell'insieme.\n\n";
   cout << "   test con esito positivo:\n";
   cout << "      appartiene(a) = " << this->appartiene(a) << "\n";
   cout << "   test con esito negativo:\n";
   cout << "      b = ";
   tipoelem b;
   cin >> b;
   cout << "      appartiene(b) = " << this->appartiene(b) << "\n\n";
   system("pause");
   system("cls");
}
insiemel.h
codice:
#ifndef insiemel_h
#define insiemel_h

#include<iostream>
#include<stdlib.h>
#include "listap.h"
//#include "insieme.h"
using namespace std;

template<class tipoelem>
class insiemel : public insieme<tipoelem>
{
   public:
      insiemel();
      
      void creainsieme();
      bool insiemevuoto();
      bool appartiene(tipoelem);
      void inserisci(tipoelem);
      void cancella(tipoelem);
      void unione(&insiemel<tipoelem>, &insiemel<tipoelem>);
      void intersezione(&insiemel, &insiemel);
      void differenza(&insiemel, &insiemel);
      
      tipoelem getelem(typename listap<tipoelem>::posizione);
      typename listap<tipoelem>::posizione getsuc(typename listap<tipoelem>::posizione);
      typename listap<tipoelem>::posizione primo();
      
      int card;
   private:
      listap<tipoelem> *set;
};

#endif

template<class tipoelem>
tipoelem insiemel<tipoelem>::getelem(typename listap<tipoelem>::posizione pos)
{
   return(set->leggilista(pos));
}

template<class tipoelem>
typename listap<tipoelem>::posizione insiemel<tipoelem>::getsuc(typename listap<tipoelem>::posizione pos)
{
   return(set->suclista(pos));
}

template<class tipoelem>
typename listap<tipoelem>::posizione insiemel<tipoelem>::primo()
{
   return(set->primolista());
}

template<class tipoelem>
insiemel<tipoelem>::insiemel()
{
   this->creainsieme();
}

template<class tipoelem>
void insiemel<tipoelem>::creainsieme()
{
   set = new listap<tipoelem>;
   card = 0;
}

template<class tipoelem>
bool insiemel<tipoelem>::insiemevuoto()
{
   return(set->listavuota());
}

template<class tipoelem>
bool insiemel<tipoelem>::appartiene(tipoelem elem)
{
   typename listap<tipoelem>::posizione p = set->primolista();
   bool trovato = false;
   while(!set->finelista(p) && !trovato)
   {
      if(set->leggilista(p) == elem)
         trovato = true;
      else
         p = set->suclista(p);
   }
   return trovato;
}

template<class tipoelem>
void insiemel<tipoelem>::inserisci(tipoelem elem)
{
   if(!this->appartiene(elem))
      set->inslista(set->primolista(), elem);
   card++;
}

template<class tipoelem>
void insiemel<tipoelem>::cancella(tipoelem elem)
{
   typename listap<tipoelem>::posizione p = set->primolista();
   bool trovato = false;
   while(!set->finelista(p) && !trovato)
   {
      if(this->getelem(p) == elem)
      {
         set->canclista(p);
         trovato = true;
         card--;
      }
      else
         p = set->suclista(p);
   }
}

template<class tipoelem>
void insiemel<tipoelem>::unione(insiemel<tipoelem>::insiemel &A, insiemel<tipoelem>::insiemel &B)
{
   typename listap<tipoelem>::posizione p = A.primolista();
   int cardA = A.card;
   while(cardA > 0)
   {
      this->inserisci(A.getelem(p));
      p = A.getsuc(p);
      cardA--;
   }
   p = B.primo();
   int cardB = B.card;
   while(cardB > 0)
   {
      this->inserisci(B.getelem(p));
      p = B.getsuc(p);
      cardB--;
   }
}

template<class tipoelem>
void insiemel<tipoelem>::intersezione(insiemel<tipoelem> &A, insiemel<tipoelem> &B)
{
   typename listap<tipoelem>::posizione p = A.primo();
   int cardA = A.card;
   while(cardA > 0)
   {
      if(B.appartiene(A.getelem(p)))
         this->inserisci(A.getelem(p));
      p = A.getsuc(p);
      cardA--;
   }
}

template<class tipoelem>
void insiemel<tipoelem>::differenza(insiemel<tipoelem> &A, insiemel<tipoelem> &B)
{
   typename listap<tipoelem>::posizione p = A.primo();
   int cardA = A.card;
   while(cardA > 0)
   {
      if(!B.appartiene(A.getelem(p)))
         this->inserisci(A.getelem(p));
      p = A.getsuc(p);
      cardA--;
   }
}
testinsieme.cpp
codice:
#include "insieme.h"
#include "insiemev.h"
#include "insiemel.h"
#include<iostream>
#include<stdlib.h>

using namespace std;

int main()
{
   cout << "                ***test insieme con vettore***\n\n";
   int dim = 10;                  
   insiemev<int> ins(dim);
   ins.inserisci(2);
   ins.test();
   cout << "                ***test metodo UNIONE***\n\n";
   cout << "ins = {";
   ins.visualizzains();
   cout << "}\n";
   int dim2 = 5;
   insiemev<int> ins2(dim2);
   ins2.inserisci(4);
   ins2.inserisci(2);
   cout << "ins2 = {";
   ins2.visualizzains();
   cout << "}\n";
   int card3 = dim + dim2;
   insiemev<int> ins3(card3);
   cout << "ins3 = unione(ins, ins2) = {";
   ins3.unione(ins, ins2);
   ins3.visualizzains();
   cout << "}\n\n";
   cout << "                ***test metodo INTERSEZIONE***\n\n";
   int dim4 = dim;
   insiemev<int> ins4(dim4);
   ins4.intersezione(ins, ins2);
   cout << "ins4 = intersezione(ins, ins2) = {";
   ins4.visualizzains();
   cout << "}\n\n";
   cout << "               ***test metodo DIFFERENZA***\n\n";
   int dim5 = dim;
   insiemev<int> ins5(dim5);
   ins5.differenza(ins, ins2);
   cout << "ins5 = differenza(ins, ins2) = {";
   ins5.visualizzains();
   cout << "}\n\n";
      
   system("pause");
   return 0;
}
l'errore che mi viene visualizzato è il seguente:
21 C:\Dev-Cpp\Strutture\Insiemi\insiemel.h variable or field `unione' declared void

lo so che il metodo unione non restituisce nessun valore. perchè me lo ricorda e me lo segnala come errore?