Содержит любой шаблонный класс C ++ в переменной-члене - PullRequest
6 голосов
/ 23 августа 2011

У меня есть два класса.

Первый класс (A) построен с использованием шаблона.

template <class T>
class A
{
    public:
        T value;
};

Второй класс (B) должен иметь объект класса A какпеременная-член.Например:

class B
{
    public:
        A<int> value;
};

Но теперь я хочу использовать любой тип шаблона-класса в классе А. Не только int .Видимо, я не могу объявить переменную (member-), которая содержит какой-либо класс.Итак, мне нужно что-то вроде этого:

class B
{
    public:
        A<*> value;
};

Есть ли (чистое) решение этой проблемы?

- Приветствие из Германии, Бастиан

Ответы [ 5 ]

7 голосов
/ 23 августа 2011

Вы не можете иметь один класс B с «любым» объектом-членом, потому что B должен быть четко определенным классом, а A<T> - это другой тип для разных типов T.Вы можете либо сделать B сам шаблон:

template <typename T>
class B
{
  A<T> value;
};

, либо взглянуть на boost::any, который является контейнером для стирания типов для произвольных типов (но с использованиемиз этого требует определенного количества дополнительной работы).Класс any работает только для типов value , однако он не является полностью произвольным.

3 голосов
/ 23 августа 2011

Самое простое решение - сделать все варианты А наследуемыми от общего интерфейса, даже если он пуст:

class IA{}

template <class T>
class A : public IA
{
    public:
        T value;
};

class B
{
    public:
        IA* value;
};

Теперь связанные затраты:

  • взаимодействия сзначение ограничено интерфейсом IA;
  • , если вы пытаетесь привести тип к реальному типу, это означает, что вы знаете настоящий тип, так что он бесполезен, и сделать тип A параметром B становится действительно прощеиспользовать.
  • существуют затраты времени выполнения, связанные с наследованием времени выполнения

Преимущество:

  • это легко понять другим разработчикам
  • этоестественно ограничить возможные типы некоторыми
  • он не использует повышение (иногда вы просто не можете)

Так что для улучшения есть другие, менее простые решения, нокоторые достаточно просты для использования:

Если вы можете использовать boost, boost :: any, boost :: variable и boost :: mpl, это может быть основой решений.

Boost any может бытьиспользуется в качестве безопасной замены для аннулирования *.Единственная проблема с этим заключается в том, что вы можете иметь ЛЮБОЙ тип, например, если тип был параметром шаблона класса B.

Вариант повышения может успешно использоваться, если вы знаете все типы, которые могут быть в A.

MPL может быть полезен, если вы просто хотите установить список возможных типов и убедиться, что ваши участники относятся только к ним.Вы можете сделать кучу вещей с MPL, так что это действительно зависит от ваших конкретных потребностей.

2 голосов
/ 23 августа 2011

Думаю, у вас есть два варианта. Первый заключается в параметризации вашего класса по параметрам типа переменных экземпляра:

template <class T> struct B
{
  A<T> value;
};

Другой вариант - объявить value как указатель void*. (Но это, вероятно, не то, что вы хотите).

1 голос
/ 23 августа 2011

Я думаю, что это помогает понять, что шаблонные классы создают совершенно новый и отдельный класс для каждого типа, который вы используете с ним. Например, Vector<int> и Vector<float> отделены от классов VectorInt и VectorFloat.

Для класса B вы в основном запрашиваете, чтобы переменная value была A<int> или A<float>, что аналогично тому, что вы хотите, чтобы значение было либо "A_int", либо "A_float". И для этого вы ... ну, используйте другой шаблон!

1 голос
/ 23 августа 2011

да, это уже сделано. подталкивание :: любой .

...