2011-08-15 27 views
31

Ben templated class (o Foo call) birkaç uzmanlık sahip olduğu. Birisi, Foo'un özel olmayan bir sürümünü kullanmaya çalıştığında derlemenin başarısız olmasını isterim. İşte Uzman olmayan şablon örneği nasıl önlenir?

Aslında ne var: Yani

template <typename Type> 
class Foo 
{ 
    Foo() { cannot_instantiate_an_unspecialized_Foo(); } 

    // This method is NEVER defined to prevent linking. 
    // Its name was chosen to provide a clear explanation why the compilation failed. 
    void cannot_instantiate_an_unspecialized_Foo(); 
}; 

template <> 
class Foo<int> 
{ }; 

template <> 
class Foo<double> 
{ }; 

o:

int main() 
{ 
    Foo<int> foo; 
} 

İşleri ederken:

int main() 
{ 
    Foo<char> foo; 
} 

yok mu. bağlama işlemi gerçekleştiğinde

Açıkçası, derleyici zinciri sadece şikayet ediyor. Ama daha önce şikayet etmenin bir yolu var mı?

Ben boost kullanabilirsiniz.

template <typename Type> 
class Foo; 

template <> 
class Foo<int> { }; 

int main(int argc, char *argv[]) 
{ 
    Foo<int> f; // Fine, Foo<int> exists 
    Foo<char> fc; // Error, incomplete type 
    return 0; 
} 

Neden bu işi yapar:

cevap

35

Sadece sınıfını tanımlamak değil mi? Basitçe, , herhangi bir genel şablon olmadığı için. Açıklandı, evet, ancak tanımlanmadı.

template <typename> class Foo;    // no definition! 

template <> class Foo<int> { /* ... */ }; // Foo<int> is OK 
+1

Çok teşekkür ederim. Sanırım çok karmaşık bir şey arıyordum. – ereOn

+0

@Schnommus Ama sınıfını tanımlamak ve bu bir static_assert varsa uzmanlık daha iyi eşleştiği için, bu örneği asla olmamalı? –

+0

Bu kötü bir karardır, çünkü derleme aşamasında değil, bağlantı aşamasında hata verilecektir. Ve uzmanlık alanı olmayan bir sınıfı nerede kullandığınızı asla bilemezsiniz. – vladon

17

Sadece temel durumunun olamaz tanımlanmamış birincil şablon) bırakarak daha:

template<typename T> 
struct dependent_false: std::false_type {}; 

template<typename Type> 
struct Foo { 
    static_assert(dependent_false<Type>::value 
       , "Only specializations of Foo may be used"); 
}; 

iddiası sadece Foo birincil şablonla örneği zaman tetikleyecektir. static_assert(false, ...) kullanmak her zaman iddiayı tetikler.

+6

Bunu özlediğime inanamıyorum ... Teşekkür ederim. Kabul edilen Schnommus'un cevabı daha düşük bir itibara sahip. Bunu adalet için kışkırttın. – ereOn

13

C++ 0 x (aynı zamanda C++ 03 static_assert emülasyonuyla mevcuttur, ancak hata iletisi için bir hile mutlaka daha iyi değildir:

+0

+1. Numara için teşekkürler. – ereOn

+2

Yazmaya daha az ihtiyaç duyan benzer bir numara static_assert kullanmaktır (sizeof (Type) == 0, "..."); Alternatif olarak BOOST_STATIC_ASSERT kullanabilirsiniz. Ben şahsen tercih ederim, çünkü yukarıdaki "temel şablonu tanımlama", sadece referanslarla/işaretçilerle çalışırken bağlayıcı hatalara yol açabilir. Eğer gerçekten bu gerekiyorsa şablonlar Bu nasıl çalışıyor burada – PlasmaHH

+0

sınırlandırıyoruz olan jenerik olmak içindir olarak da sıklıkla, bir an için durup yeniden düşünmek gerekir? Eğer 'dependent_false tanımlamanız gerekir olmaz: std :: true_type {}', ya da başka her 'Specialization' için' :: value' hep yanlış olur dependent_false? – mako

İlgili konular