2013-04-30 27 views
8

bu düşünün? Başka bir deyişle, aşırı yüklenen bir işlev şablonunun dönüş değerini hesaplarken, statik bir sonlandırma başarısızlığının, bir tetikleyici tipte tetiklenip tetiklenmediğini, derlemeyi durdurması veya aşırı yüklenmenin atılması isteniyor mu diye sormak istiyorum.Statik iddialar ve SFINAE

gcc 4.7'de derleme başarısız. Bu oldukça gcc 4.8 (ancak bu anda kontrol edemezsiniz) derler. Kim haklı?

+0

olası yinelenen [Bir müşteriyi birincil şablon yerine açıkça özelleştirilmiş bir şablonu çağırmaya nasıl zorlayabilirim?] (http://stackoverflow.com/questions/16286303/how-can-i-force-a-client-to-call- bir-açıkça-özelleştirilmiş-şablon yerine-of-t) –

cevap

12

Derleme, herhangi bir uyumlu derleyicide başarısız olmalıdır.

SFINAE kuralları, açıklamalara değil, tanımlara dayanmaktadır.

template < /* substitution failures here are not errors */ > 
struct my_struct { 
    // Substitution failures here are errors. 
}; 

bir fonksiyonu için: Ek olarak

template </* substitution failures here are not errors */> 
/* substitution failures here are not errors */ 
my_function(/* substitution failures here are not errors */) { 
    /* substitution failures here are errors */ 
} 

bir sınıf/yapı için

: (. Ben burada yanlış terminoloji kullanarak olmam durumunda Maalesef) Demek şudur Verilen şablon argümanları dizisi için yapının/fonksiyonun varlığı da SFINAE kurallarına tabidir.

Artık bir static_assert, yalnızca ikame arızalarının hata olduğu bölgelerde görünebilir ve bu nedenle, eğer bir yangın çıkarsa, bir derleyici hatası alırsınız. o zaman kod derler ve çıkışlar

false için enable_if uzmanlaflmas kaldırırsanız Sonra

// Primary template (OK) 
template <bool, typename T> 
struct enable_if; 

// Specialization for true (also OK) 
template <typename T> 
struct enable_if<true, T> { 
    using type = T; 
}; 

// Specialization for false (Wrong!) 
template <typename T> 
struct enable_if<false, T> { 
    static_assert(std::is_same<T, T*>::value, "No SFINAE here"); 
    // The condition is always false. 
    // Notice also that the condition depends on T but it doesn't make any difference. 
}; 

bu

template <typename T> 
typename enable_if<std::is_integral<T>::value, int>::type 
test(const T &t); 

void test(...); 

int main() 
{ 
    std::cout << std::is_same<decltype(test(0)), int>::value << std::endl; // OK 
    std::cout << std::is_same<decltype(test(0.0)), void>::value << std::endl; // Error: No SFINAE Here 
} 

deneyin:

Örneğin şu enable_if bir yanlış uygulama olur

1 
1 
+0

Kapsamlı açıklama için cevabı kabul edildi olarak işaretleyin. – bluescarni

6

gcc 4.7'de derleme başarısız. Bu oldukça gcc 4.8 (ancak bu anda kontrol edemezsiniz) derler. Kim haklı?

Statik iddianızdaki koşul herhangi bir şablon parametresine bağlı değildir. Bu nedenle, derleyici, şablonu ayrıştırırken onu hemen false olarak değerlendirebilir ve onaylama işleminin - aslında şablonu başka bir yerde gerçekten başlatıp açmayacağınız farketmez - gerçekleştirmesi gerektiğini anlayabilir.

Aynı şey herhangi bir derleyicide geçerli olmalıdır.

+0

Yeterince adil, bir süre GCC 4.8 tam olarak neler olup bittiğini kontrol edeceğim. Sanırım temel soru, static_assert() bir "ikame hatası" veya daha ciddi bir şey olarak sayıyorsa? – bluescarni

+0

@bluescarni: Bu bir "ikame hatası" değil, daha ziyade zor bir hatadır, çünkü ["anında bağlamda]] (http://stackoverflow.com/questions/15260685/what-is-exactly-the İşlev türü ve onun parametre parametre türleri –

+0

@Andy - -im-in-the-c11-için-in-whic-bağlamında-orta-bağlamında). Static_assert'teki koşulun T'ye bağlı olmaması gerçeğinin bir fark yaratmadığına inanıyorum. Lütfen, cevabıma bir göz atın ve bunu geliştirmekten çekinmeyin. –