2012-03-30 16 views
5

Nesnenin oluşturulmasını yöneten World sınıfım var ... Oluşturulduktan sonra afterCreation yöntemini çağırdım ve oluşturulan nesne Kullanıcıdan türetilmiş kullanıcı tanımlı tiptir (ör. MyEntity), addEntity'u aramak istiyorum. Nesne başka bir şeydi, hiçbir şey yapmak istemiyorum. o vb her türetilmiş sınıf İşteBelirli türden türetilen tür için şablon nasıl uzmanlaşır?

için benzersiz kimlikler oluşturur çünkü addEntity uygun T çağrılmalıdır benim çözümdür:

template <int v> 
struct ToType 
{ 
    enum { value = v }; 
}; 

template <typename T> 
void World::afterCreation(T * t) 
{ 
    afterCreation(t, ToType<std::is_base_of<Entity, T>::value>()); 
} 

template <typename T> 
void World::afterCreation(T * t, ToType<true>) 
{ 
    addEntity(t); //here I cant pass Entity *, I need the real type, eg. MyEntity 
} 

template <typename T> 
void World::afterCreation(T * t, ToType<false>) 
{ 

} 

Benim soru - daha iyi bir yol yapılabilir mi?

Aşağıdaki kodu ToType veya benzeri olmadan nasıl simüle edebilirim?

template <typename T> 
void afterCreation(){/*generic impl*/} 

template <typename T where T is derived from Entity> 
void afterCreation(){/*some specific stuff*/} 
  • başlığında niyetimi açıklamak için sadece "uzman", Sen polimorfik işaretçiler ile yapabilirsiniz

cevap

3

O çok daha iyi hale getirmek için gitmiyor, ancak SFINAE kullanarak dolaylama bir seviye kaldırabilirsiniz:

Bu nasıl çalışıyor
template <typename T> 
typename std::enable_if< std::is_base_of<Entity, T>::value >::type 
World::afterCreation(T * t) 
{ 
    // Derived from Entity 
} 
template <typename T> 
typename std::enable_if< !std::is_base_of<Entity, T>::value >::type 
World::afterCreation(T * t) 
{ 
    // generic 
} 

? Derleyici, afterCreation numaralı aramayı bulduğunda, aşırı yüklerden hangilerinin en iyi olduğunu bulmaya çalışır ve bunun için türlerle eşleşir ve değiştirmeyi dener. Her iki durumda da, eşleştirilen tür (argümanlardan) ve ikameyi tüm ifadeye uygular. İlk bağımsız değişken olarak iletilen değer true ise enable_if şablonu iç türü type içeriyorsa veya bu tür içermiyorsa. Tiplerin değiştirilmesi sırasında, aşırı yüklenmelerden biri geçersiz bir fonksiyon imzası (durumun yanlış olduğu durum) verecektir ve aday kümesinden düşülecektir.

1

şablon uzmanlık ile sorunu çözmek gerek:

template <typename T> 
void afterCreation(T* x) { 
    T* entity = dynamic_cast<Entity*> x; 

    if (!entity) { 
     // ... generic implementation 
    } else { 
     // ... entity implementation, use "entity" 
    } 
} 

Bu, (minik) bir çalışma süresi yüküne sahip olduğundan, bu en iyi çözüm olmayabilir. Çok akıllı bir derleyici bu ek yükü statik analizden çıkarabilir ancak derleyicilerin bunu seçeceğinden şüphe duyuyorum.

+0

Eddie Edwards: Sadece üzerinde çalışmasını istediğiniz nesnenin işaretçisini geçirerek. Varlık x; AfterCreation (&x);1. – orlp

+0

+1, basit ve noktaya :) Sorunun ne olduğunu sormak yerine asıl sorunu çözer (SFINAE'den çok daha basit bir yaklaşımla) - fonksiyonda hiçbir şeyin sadece "derleyeceğini" varsayıyorum Varlık türetilmiş türler, yani varlık türü türetilmiş türler için derleme yapamayacak "varlık -> getEntityName()" gibi bir şey yoktur) –

+0

Üzgünüz gece bekçisi yorumlarımı destekledim (ve yanıtlanmamış yanıtınıza uyguladılar) derleyicinin çoğu, x türüyle ilgili tam bilgiye sahip olduğu için dynamic_cast öğesini kaldıracaktır. Ya da en azından, tempile edilmiş çözümün işe yarayabileceğini varsayarak, ihtiyaç duyduğu kadar bilgi. –

İlgili konular