2016-01-15 23 views
7

this article about type erasure okuyordum. Ama bu makaledeki kod örneğin kısmen yanlış görünüyor: C++ cinsinden tip silme nedir?

template <typename T> 
class AnimalWrapper : public MyAnimal 
{ 
    const T &m_animal; 

public: 
    AnimalWrapper(const T &animal) 
     : m_animal(animal) 
    { } 

    const char *see() const { return m_animal.see(); } 
    const char *say() const { return m_animal.say(); } 
}; 

Bu hatalar daha fazla makalesinde okumasını beni cesaretini

void pullTheString() 
{ 
    MyAnimal *animals[] = 
    { 
     new AnimalWrapper(Cow()), /* oO , isn't template argument missing? */ 
     .... 
    }; 
} 

izledi.

Neyse; C++'daki tip silme işleminin ne anlama geldiğini basit örnekler ile öğrenebilir misiniz?

std::function'un nasıl çalıştığını anlamak için bunun hakkında bilgi edinmek istedim, ancak kafamı bulamadım.

+0

ilgili /, yinelenen: http://stackoverflow.com/questions/5450159/type-erasure-techniques Ya, 't' deduces ve '' geçen bir fonksiyonu '' geçmesi veya kullanmak gerekir – NathanOliver

+1

. Yani, şablon MyAnimal * WrapAnimal (T const & t) {yeni AnimalWrapper (t);} döndürün ve 'yeni AnimalWrapper'ı' WrapAnimal' ile değiştirin. – Yakk

+0

@NathanOliver Bu soruda OP, halihazırda tip silme ile ilgili temel kavramları bilir. –

cevap

10

Burada eylem türü silinmeye çok basit bir örnek:

// Type erasure side of things 

class TypeErasedHolder 
{ 
    struct TypeKeeperBase 
    { 
    virtual ~TypeKeeperBase() {} 
    }; 

    template <class ErasedType> 
    struct TypeKeeper : TypeKeeperBase 
    { 
    ErasedType storedObject; 

    TypeKeeper(ErasedType&& object) : storedObject(std::move(object)) {} 
    }; 

    std::unique_ptr<TypeKeeperBase> held; 

public: 
    template <class ErasedType> 
    TypeErasedHolder(ErasedType objectToStore) : held(new TypeKeeper<ErasedType>(std::move(objectToStore))) 
    {} 
}; 

// Client code side of things 

struct A 
{ 
    ~A() { std::cout << "Destroyed an A\n"; } 
}; 

struct B 
{ 
    ~B() { std::cout << "Destroyed a B\n"; } 
}; 

int main() 
{ 
    TypeErasedHolder holders[] = { A(), A(), B(), A() }; 
} 

[Live example]

Gördüğünüz gibi, TypeErasedHolder keyfi bir tür nesneler saklayabilir ve bunları doğru şekilde imha edebilirsiniz. Önemli olan, desteklenen (1) türlerine herhangi bir kısıtlama getirmemesidir: örneğin ortak bir tabandan türetmek zorunda değillerdir.


(1) tabii ki, hareket edebilir hariç.

+0

Hm, neden '' TypeKeeper' için iletmek için '' TypeErasedHolder'' ve '' std :: forward'' yapıcı argümanı için '' && '' (evrensel başvuru (?)) Kullanmıyorsunuz? '? (burada anlamaya çalışmak, her zaman bir kopyasını alıp orijinal nesneyi taşımak yerine o kopyadan taşıyormuşsunuz gibi görünüyor) –

+1

@JonasWielicki Örneğin "çok basit" yönünü korumak için. Bir yönlendirme başvurusu kullanmak, 'TypeKeeper' vb. Şablon argümanı için 'std :: remove_reference' kullanılmasını da gerektirir. – Angew

+0

Açıklama için teşekkürler! –