2013-07-16 13 views
7

static_assert'un yararlılığını anlamaya çalışıyorum ve bir tasarımın uygulanmasında bana yardımcı olup olmayacağını öğrenmek istiyorum ve eğer öyleyse nasıl.Statik_assert üzerinden şablon türü zorlayın

Kendi uygulamanızı, şablon türünün boyutuna göre kısmen özelleştirilmiş olan başka bir şablon sınıfında gizleyen genel bir şablon sınıfım var. İşte bu tasarımın kısa bir anahat: T büyüklüğü Yardımcısı bir uzmanlaşma tarafından desteklendiği takdirde

template <class T, size_t S = sizeof(T)> 
struct Helper; 

template <class T> 
struct Helper<T, sizeof(long)> 
{ 
    static T bar(); 
}; 

// ... other specializations ... 

template <class T> 
class Foo 
{ 
public: 

    T bar() 
    { 
     return Helper<T>::bar(); 
    } 
}; 

Foo desteklenir. Örneğin, Foo<long> ve Foo<unsigned long> her ikisi de desteklenmektedir. Bununla birlikte, kullanıcının bir Foo<bool> oluşturmayı denediğini varsayalım. Normalde, bu hata üretecektir çünkü Yardımcı'un bool için özelleşmesi tanımlanmamıştır, bu da amaçlanan davranıştır.

Bu arabirimdeki kullanıcı için daha yararlı hatalar sağlamak amacıyla bu tasarımda static_assert'u kullanmanın bir yolu var mı?

Ayrıca, boyut doğru olsa bile, kullanıcının belirli bir tür kullanmasını kısıtlamak isterim. Örneğin, Foo<float>'a izin verilmemelidir. Şu an bunu benimsemeyi bildiğim tek yol, belgelerdeki cesur bir yorum. sadece şablon sınıfın bir uzmanlık için çalışabilir varsa :)

+0

Daha genel olarak düşünün, sadece desteklenen tamsayı türleri mi? Hayır "char", "bool", "float" ve diğerleri? – Rapptz

+0

Şablon türü kısıtlamaları veya "kavramlar" için SO ara. Bunu yapmak için bir tesis son dakikada C++ 11'den kaldırıldı. Benzer sonuçlara ulaşmak için daha az otomatik yol vardır. – luke

+0

@Rapptz, 'char',' int' ve 'long', 'unsigned' sürümleriyle birlikte desteklenmelidir. 'Int', 'long' ve' unsigned long' için de özdeş olacaktır. – Zeenobit

cevap

1

Burada cevapları ve yorumları birleştirerek bu sorun için daha iyi bir çözüm bulduk.

ben şöyle statik tip kontrolörü tanımlayabilirsiniz:

template <class A, class B> 
struct CheckTypes 
{ 
    static const bool value = false; 
}; 

template <class A> 
struct CheckTypes<A, A> 
{ 
    static const bool value = true; 
}; 

emin değil böyle bir yapı zaten standart kütüphanede varsa.Neyse, sonra Fooyılında, kullanıyorum türleri ve boyutları için kontrol edebilirsiniz:

static_assert((sizeof(T) == sizeof(long) || sizeof(T) == sizeof(int)) && !CheckTypes<T, float>::value, "Error!"); 
+1

bunu yapar, std :: is_same –

+1

sizeof kullanarak güvenli değildir. sadece boyut. uzun ve int aynı boyutta olabilir ve sadece bir int tutan rasgele bir yapı da aynı boyuta sahip olacaktır. –

13

ardından varsayılan şablon sınıfı statik assert yükseltmek vardır:

yoksa varsayılan şablon sınıfı sadece seçilecektir
template <class T, size_t S = sizeof(T)> 
struct Helper 
{ 
    static_assert(sizeof(T) == -1,"You have to have a sepecialization for Helper!"); 
} 

Daha iyi bir uzmanlık, bu yüzden savcı yükselecek.

Türlere izin vermemek için aynı tekniği kullanabilirsiniz, ancak statik onay denetimi için kullanılacak başka bir şablon parametresine ihtiyacınız olacaktır.

template <class T, class G = T, size_t S = sizeof(T)> 
struct Helper 
{ 
    static_assert(sizeof(G) == -1,"You have to have a sepecialization for Helper!"); 
} 

template <class G> 
struct Helper<float,G> 
{ 
    static_assert(sizeof(G) == -1,"You can't use float !"); 
} 

template <> 
struct Helper<int> 
{ 
//This is a good specialization 
}; 

Daha sonra bu değişkenleri ile deneyebilirsiniz:

Helper<bool> a; //"You have to have a sepecialization for Helper!" 
Helper<float> b; //"You can't use float !" 
Helper<int> c; //compiles OK 
+1

"static_assert (false, ...)" yi istediğinizi düşünüyorum, bu yüzden her zaman gezer. İlk argüman yanlışsa, static_assert 'hatasını yazdırır. Pragmatik yanıt için –

+0

+1 – sehe

+9

Bu işe yaramayacak - iddiayı bağımlı yapmalısınız (örneğin, static_assert (sizeof (T) == 0, ...); '), aksi halde işlenir Bildiri noktası, somutlaştırma değil. – Angew

3

http://en.cppreference.com/w/cpp/header/type_traits

std::is_base_of ve std::is_convertible ilk konuyu ve saniye olarak yardımcı olabilecek,

static_assert(!std::is_same<float,T>(),"type can't be float");

Umarım bu soru üzerine tökezleyen bir başkası yardımcı olur, zira OP muhtemelen 4 yıllık bir gün içinde bir cevap buldu. ce soruldu :)

İlgili konular