2010-11-29 12 views
5

Uzun zaman önce bir referans statik döküm İşaretli ama tip I olmasını farz ne değildir: istediğimBir static_cast gerçekleştirmek zaman ben bir assert olsun ki ben şu şablonu oluşturduk

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType item) 
{ 
    Assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

Bugün

/// overload for reference 
template <class Type, class SourceType> 
Type &static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<Type *>(&item)); 
    return static_cast<Type>(item); 
} 

ancak derleyici başka referans bir başvuru döküm ediyorum bu aşırı kullanmak görünmüyor: yanı işaretçiler ile ancak referanslarla sadece çalışacak bir varyantı oluşturmak için. Korkarım ki nedenini anlamak ya da çalışan bir varyant yaratabilmek için şablon çözünürlük kurallarını anlamıyorum.

Not: Bu proje için istisnalar devre dışı bırakıldığı için dynamic_cast<Type *> NULL yerine bad_cast exception'u yakalayamıyorum.

+1

Eğer 'SourceType *' için bir aşırı ekleyebilir ve özgün bir emekli miyim? Değer türlerini desteklemeniz gerekiyor mu? (Ve bu sorunu çözüyor mu, şimdi merak ediyorum?) –

+1

Bu kod satırlarını düşündüm ve neden gerekli olduğunu anlayamıyorum. Dinamik bir döküm ile statik bir döküm olup olmadığını kontrol ederseniz, sadece nesneler dinamik dökümlü statik döküm ile kontrol edilebilir. Bu, "dynamic_cast" in yeniden yapılandırılmasıdır. Dinamik ve statik cast ist arasındaki fark, dinamik kalıba vtable ve statik olmayanı araştırır. – nutario

+0

Statik bir dökümdür, ancak bir tanesi - yani, hata ayıkladığınızı bildirir. Bu, döküm yaptığınız türle ilgili varsayımınızın yanlış olduğunu bildirir. – Suma

cevap

5

Kaldır * ve &:

Derived *d= static_cast_checked<Derived *>(b); 
Derived &d= static_cast_checked<Derived &>(b); 

DÜZENLEME:

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType *item) 
{ 
    Assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

template <class Type> struct make_pointer 
{ 
    typedef Type *PointerType; 
}; 

template <class Type> struct make_pointer<Type &> 
{ 
    typedef Type *PointerType; 
}; 

/// overload for reference 
template <class Type, class SourceType> 
Type static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<typename make_pointer<Type>::PointerType>(&item)); 
    return static_cast<Type>(item); 
} 

Sonra istenen sözdizimi kullanılabilir işaretçi tipi dönüşüm ekledi.

+1

İşaretçiyi bir referanstan ('Assert (dynamic_cast (& madde));') en azından gcc kullanıyorsanız, diğer derleyiciden emin değilim. – nutario

+0

@nutario, ah, haklısınız efendim. – MSN

+0

@nutario, sabit! – MSN

0

aşağıdaki deneyin:

template<class Type, class SourceType> 
Type* static_cast_checked(SourceType* item) 
{ 
    // ... 
} 

template<class Type, class SourceType> 
Type& static_cast_checked(SourceType& item) 
{ 
    // ... 
} 

Daha sonra, her işaretçi birinci varyantı kullanmak ve her referans kısmi uzmanlık (IIRC) kurallarına de ikinci kullanır.

2

Bu çalışır:

/// perform a static_cast asserted by a dynamic_cast 
template <class Type, class SourceType> 
Type* static_cast_checked(SourceType *item) 
{ 
    Assert(!item || dynamic_cast<Type*>(item)); 
    return static_cast<Type*>(item); 
} 

/// overload for reference 
template <class Type, class SourceType> 
Type &static_cast_checked(SourceType &item) 
{ 
    Assert(dynamic_cast<Type *>(&item)); 
    return static_cast<Type&>(item); 
} 

böyle kullanın:

Dervied d; 
Base* pbase = static_cast_checked<Base>(&d); 
Base& rbase = static_cast_checked<Base>(d); 

Bu çözüm fonksiyon şablonları aşırı güvenir. Çözümünüz işe yaramadı çünkü ilk şablonunuz çok genel, zaten ikinci fonksiyonunuzu içeriyor. Fonksiyon şablonları için uzmanlık olmadığını unutmayın! Sadece sınıf şablonlarını özelleştirebilirsiniz. dönüş türlerinden

+0

Harika, bu kolay ve oldukça iyi çalışıyor. Mümkünse, static_cast_checked veya static_cast_checked yazmam için bana izin verecek bir çözümü tercih ederim. Birisi kim oluşturabilir?Şimdi, sıkı çalışmayı yapmak için özel bir şablon sınıfını kullanmaya çalışıyorum, bu da söz veriyor. – Suma

+0

Çeşitli girişimleri denedim (tür özellikleri ve sınıf uzmanlıkları dahil) ve bir derleme çözümüne gelmedim. – WolfgangA

+0

Sanırım aşırı yük ve sınıf uzmanlıklarının bir kombinasyonu ile bir çözüm buldum. Yeni cevabımı kontrol edip, tamam olup olmadığını kontrol edebilir misiniz? – Suma

1
#include <boost/type_traits/add_pointer.hpp> 

template <class Type, class SourceType> 
Type static_cast_checked(SourceType *item) 
{ 
    assert(!item || dynamic_cast<Type>(item)); 
    return static_cast<Type>(item); 
} 

template <typename Type, class SourceType> 
Type static_cast_checked(SourceType &item) 
{ 
    typedef typename boost::add_pointer<Type>::type TypePtr; 
    assert(dynamic_cast<TypePtr>(&item)); 
    return static_cast<Type>(item); 
} 

Bu uygulama std-lib gelen static_cast veya dynamic_cast gibi çalışır: ``

Base &b = static_cast_checked<Base&>(a); 
    Base* bPtr = static_cast_checked<Base*>(&a); 
+0

Güzel. Benim çözümümün hemen hemen aynısı var ve teknik arka plan aynı, ancak destek kullanmak biraz daha kısa olabilir. – Suma

İlgili konular