Existe uma maneira de acessar as partes íntimas de uma instanciação diferente do mesmo modelo de classe?

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

  •  19-09-2019
  •  | 
  •  

Pergunta

Na minha aventura continua com modelos, eu templated minha classe Container não apenas sobre o ItemType que detém, mas também em um argumento Functor que determina como deve ordenar os itens. Tão longe, tão bom.

Um pequeno problema eu correr em ocorre quando eu quero copiar o conteúdo de um recipiente para outro: se os dois recipientes têm diferentes tipos Functor, então tecnicamente são classes não relacionadas. Portanto, Container Um não tem permissão para acessar o conteúdo não-públicas de Container B. Existe alguma boa maneira de lidar com este problema, à excepção de fazer tudo o que preciso pública de acesso? Alguma forma ao modelo de declaração "amigo", talvez?

código Exemplo para demonstrar o problema seguinte:

#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;
}
Foi útil?

Solução

Você pode fazer uma classe template base templated apenas ItemType, manter os dados lá, tem o pleno direito de 2 args modelo subclasse que base, e colocar a cópia de na classe base, uma vez que não depende a de qualquer maneira functor. Ou seja:.

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;-)
};

Outras dicas

Como você apontar, você pode também usar uma função amigo:

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;
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top