C'è un modo per accedere alle parti intime di una diversa istanza della stessa classe template?

StackOverflow https://stackoverflow.com/questions/1191944

  •  19-09-2019
  •  | 
  •  

Domanda

Nella mia avventura continua con i modelli, ho basato su modelli mia classe contenitore non solo sul ItemType che detiene, ma anche su un argomento Functor che determina come dovrebbe ordinare gli articoli. Fin qui, tutto bene.

Un piccolo problema che ho incontrato si verifica quando voglio copiare il contenuto di un contenitore all'altro: se i due contenitori hanno diversi tipi funtore, poi tecnicamente sono classi non correlate. Pertanto, Contenitore A non è consentito di accedere ai contenuti non pubbliche del container B. C'è un buon modo per affrontare questo problema, diverso rendendo tutto ho bisogno di accesso del pubblico? Qualche modo al modello di dichiarazione "amico", forse?

Codice di esempio per dimostrare il problema segue:

#include <stdio.h>

class FunctorA {};
class FunctorB {};

template <class ItemType, class Functor> class MyContainer
{
public:
   MyContainer() : _metaData(0) {/* empty */}

   template<class RHSFunctor> void CopyFrom(const MyContainer<ItemType, RHSFunctor> & copyFrom)
   {
      _metaData = copyFrom._metaData;
      _item     = copyFrom._item;
   }

private:
  int _metaData;
  ItemType _item;
};

int main(int argc, char ** argv)
{
   MyContainer<void *, FunctorA> containerA;
   MyContainer<void *, FunctorB> containerB;

   containerA.CopyFrom(containerB);  // error, containerA::CopyFrom() can't access containerB's private data!
   return 0;
}
È stato utile?

Soluzione

È possibile effettuare una classe template di base su modelli proprio sulla ItemType, conservare i dati lì, hanno il pieno titolo 2-args template sottoclasse quella base, e mettere il copia-da nella classe base in quanto non dipende funtore comunque. Cioè:.

template <class ItemType> class MyContainerBase
{
public:
   MyContainerBase() : _metaData(0) {/* empty */}

   void CopyFrom(const MyContainerBase<ItemType> & copyFrom)
   {
      _metaData = copyFrom._metaData;
      _item     = copyFrom._item;
   }

protected:
  int _metaData;
  ItemType _item;
};

template <class ItemType, class Functor> class MyContainer:
    public MyContainerBase<ItemType>
{
  // whatever you need here -- I made the data above protected
  // just on the assumption you may need to access it here;-)
};

Altri suggerimenti

Come fai notare, è anche possibile utilizzare una funzione friend:

class FunctorA {};
class FunctorB {};

template <class ItemType, class Functor> class MyContainer
{
public:
  MyContainer() : _metaData(0) {/* empty */}

  template<class CmnItemType, class LHSFunctor, class RHSFunctor>
  friend void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
    , MyContainer<CmnItemType, RHSFunctor> & copyTo);

private:
  int _metaData;
  ItemType _item;
};

template<class CmnItemType, class LHSFunctor, class RHSFunctor>
void Copy(const MyContainer<CmnItemType, LHSFunctor> & copyFrom
  , MyContainer<CmnItemType, RHSFunctor> & copyTo)
{
  copyTo._metaData = copyFrom._metaData;
  copyTo._item     = copyFrom._item;
}


int main(int argc, char ** argv)
{
  MyContainer<void *, FunctorA> containerA;
  MyContainer<void *, FunctorB> containerB;

  Copy(containerB, containerA);
  return 0;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top