Стирание типа может и было реализовано в C ++ в разных контекстах.Наиболее распространенный подход, который используется в boost::any
, std::function< signature >
, std::thread
и других, основан на неполиморфном классе, который является стертым типом *1005* объекта, который содержит указатель на интерфейстип.Внутри, во время построения, назначения или всякий раз, когда пользовательский тип стирается, реализация интерфейса сохраняется и сохраняется.
В качестве упрощенного примера мотивации, рассмотрим, что мы хотели создать printable
тип, который может бытьиспользуется для печати любого типа, который реализует operator<<
до std::cout
, используя стирание типа.Для этого нам понадобится тип printable
, внутренний интерфейс printable_impl_base
и фактические реализации:
// regular polymorphic hierarchy:
struct printable_impl_base {
virtual ~printable_impl_base() {}
virtual void print() const = 0;
};
template <typename T>
struct printable_impl : printable_impl_base {
T copy_to_print;
printable_impl( T const & o ) : copy_to_print( o ) {}
virtual void print() const {
std::cout << copy_to_print << std::endl;
}
};
// type erasure is performed in printable:
class printable {
std::shared_ptr<printablable_impl_base> p;
public:
template <typename T>
printable( T obj ) : p( new printable_impl<T>(obj) ) {}
void print() const {
p->print();
}
};
Обратите внимание, что шаблон очень похож на обычную полиморфную иерархию с той разницей, что интерфейс добавлен объект, представляющий собой тип значения (заимствующий термин тип значения из C #), который содержит фактические полиморфные объекты внутри.
Глядя на это таким образом,это кажется несколько упрощенным и бесполезным, но это топливо, которое управляет boost::any
(внутренний интерфейс - это только typeid), std::function< void () >
(внутренний интерфейс реализует void operator()
) или shared_ptr<>
(интерфейс - это метод удаления, который освобождает ресурс).
Существует один конкретный другой тип стирания типа, когда единственное, что нужно сделать с типом, реализующим стирание типа, - это уничтожить его: использоватьвременно и связать его с постоянной ссылкой ... Но это очень специфично, если вы хотите, вы можете прочитать об этом здесь: http://drdobbs.com/cpp/184403758
ВВ конкретном случае, о котором вы говорите в этом вопросе, он немного сложнее, потому что вы не хотите удалять один тип, а скорее пару из них.Интерфейс Iterable
должен удалять тип контейнера, который он содержит внутри, и при этом он должен предоставлять свои собственные итераторы, которые должны выполнять стирание типа на итераторах из контейнера.Тем не менее, идея в основном та же самая, просто больше работы, чтобы сделать.