Можно ли указать абстрактный тип переменной класса через шаблон? - PullRequest
1 голос
/ 13 июня 2019

В контексте API я хотел бы минимизировать классы, доступные пользователю.С этой целью я хотел бы обобщить тип данных, к которым он имеет доступ, но специализировать входные данные.

Я думал о шаблонах.Однако я из мира C # и не привык к возможностям и ограничениям шаблонов в мире C ++.

Вот некоторый псевдокод:

GenericAnimal<T>
bool setSubSpecies(T.EnumOfSubSpecies subSpecies)
GenericAnimal<Fish> cod;
cod.setSubSpecies(Fish.FishSubSpeciesEnum.Cod);
GenericAnimal<Mammal> cetacean;
cetacean.setSubSpecies(Mammal.MammalSubSpeciesEnum.Cetaceans);

Альтернативой может быть создание класса Fish, производного от GenericAnimal<T1, T2, ...>, с соответствующими шаблонными классами, но, как я уже сказал, я бы хотел избежать обилия классов и определить T1, T2, ... через уникальный класс / структуру.

Редактировать: исправление опечаток кода.

1 Ответ

1 голос
/ 13 июня 2019

Я не уверен, что полностью понимаю ваш вопрос, но может ли это быть тем, что вы ищете?

template <class T>
class GenericAnimal
{
public:
  bool setSubSpecies(typename T::SubSpeciesEnum)
  {
    // code here
  }
};


class Fish
{
public:
  enum SubSpeciesEnum {
    Cod, Salmon, Carp
  };
};

class Mammal
{
public:
  enum SubSpeciesEnum {
    Cetaceans, Canids, Felines
  };
};


GenericAnimal<Fish> cod;
cod.setSubSpecies(Fish::SubSpeciesEnum::Cod);

GenericAnimal<Mammal> cetaceans;
cod.setSubSpecies(Mammal::SubSpeciesEnum::Cetaceans);

Предостережение, конечно, заключается в том, что, будучи шаблоном, GenericAnimal должен быть либо полностью реализован в заголовке, либо предварительно специализирован в вашей библиотеке для всех типов, с которыми он может быть создан (а клиент не сможет использовать его с другими типами).


Чтобы ответить на дополнительный вопрос из комментариев

Можем ли мы иметь класс Fish как сам шаблон, производный от AnimalAttributes<T1>, T1, являющийся SubSpeciesEnum?

Это невозможно напрямую, потому что нет способа объявить Fish::SubSpeciesEnum перед его использованием в базовом классе AnimalAttributes. Однако существуют обходные пути, такие как введение промежуточного базового класса:

class FishEnum
{
public:
  enum SubSpeciesEnum {
    Cod, Salmon, Carp
  };
};

template <class EnumClass>
class AnimalAttributes : public EnumClass {
public:
  using typename EnumClass::SubSpeciesEnum;
};

class Fish : public AnimalAttributes<FishEnum>
{
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...