Улучшенные общие указатели шаблонов не будут выполнять магию, которую вы не сможете сделать без обычных указателей (а именно, поместить два разных типа в одну коллекцию). Всякий раз, когда вы используете шаблон, вы должны явно объявить аргументы шаблона, потому что все, что делает шаблон - это генерирует дублирующий код для вас во время компиляции. Поэтому, когда вы используете шаблон, компилятор просто дублирует файл шаблона столько раз, сколько вы объявили с аргументами шаблона. Нет аргументов шаблона, нет дублирования, нет шаблона. По крайней мере, это мое понимание, я уверен, что полиция C ++ исправит меня, если я ошибаюсь.
Таким образом, способ поместить два разных типа в одну коллекцию - это замаскировать значение, помещаемое в коллекцию. Самый простой способ сделать это (и плохой способ) - создать коллекцию пустых указателей, а затем использовать вставку и извлечение в зависимости от контекста. Это опасно, потому что тогда вы будете получать доступ к памяти через указатель без проверки того, что указатель указывает на правильный объем / формат памяти (это проверка типа).
Итак, реальный способ сделать это, как предложил пмр. Сделайте свою коллекцию коллекцией указателей базового типа и используйте динамическое приведение для приведения между типами при вставке и извлечении из списка. Динамическое приведение проверит во время выполнения, чтобы убедиться, что тип, из которого вы преобразуете, и из которого совместимы. То есть, если вы преобразуете из Derived1 в Base, а затем из Base в Derived1, это нормально. Если вы преобразуете из Derived1 в базу, а затем из базы в Derived2 по указателю, указывающему на ту же память, во время выполнения произойдет сбой, поскольку Derived2 и Derived1 несовместимы.
Это объяснение немного длинное, потому что у меня была такая же проблема с дизайном несколько месяцев назад, пока я не прочитал немного.