2012-07-02 21 views
6

enable_if O SFINAE enable_if ile decltype kullanarak basit değilmiş.kullanarak go'u üç farklı şekilde yazmayı denedim. Hepsi bir derleyici hatası ile başarısız oldu (GCC ile tam anlamıyla: "hata: 'şey', 'foo' nun bir üyesi ve bir somutlaşma bağlamı değildir). enable_if bile işlevini ekarte etmek fırsatı olmadan gerçekleşmesi gerekiyor decltype -Karıştırma decltype ve

#include <type_traits> 

struct foo { 
    enum { has_thing = false }; 
}; 

struct bar { 
    enum { has_thing = true }; 
    static int thing() { return 0; } 
}; 

template <typename T> 
struct Test { 
    /*auto go(typename std::enable_if<T::has_thing, int>::type=0) 
    -> decltype(T::thing()) { 
    return T::thing(); 
    }*/ 

    /*typename std::enable_if<T::has_thing, decltype(T::thing())>::type go() { 
    return T::thing(); 
    }*/ 

    template <bool B=T::has_thing, typename std::enable_if<B, int>::type = 0> 
    auto go() -> decltype(T::thing()) { 
    return T::thing(); 
    } 
}; 

int main() { 
    Test<bar> b; 
    Test<foo> f; 
} 

Sorunun ne görebiliriz. Kalan soru, etrafta nasıl çalışılacağı ve benzer davranışların nasıl ele alınacağıdır?içinde kullanmak için has_thing özellik yazma başvurmadan basit, genel bir yolu var mı? G, her iki ile test edilmiştir

++ 4.7 ve çınlama ++ 3.0. senin SFINAE çalışmıyor Tabii

+1

Derleyici hatasını gönderir misiniz? Ayrıca, derleyici sürümü yardımcı olacaktır. Bu bölümdeki derleyiciler hala çok yorucu olduğu deneyimlerinden söyleyebilirim. –

cevap

5

go yöntemi şablon yöntemi ise SFINAE çalışacaktır:

template <typename T> 
struct Test { 
    template <class U = T> 
    auto go() -> decltype(U::thing()) { 
    return T::thing(); 
    } 
}; 

Ayrıca has_thing değeri kullanmak, ancak gerek yoktur

template <class U = T, typename std::enable_if<U::has_thing, int>::type = 0> 
auto go() -> decltype(U::thing()) { 
    return T::thing(); 
} 

Sonra:

SFINAE yukarıdaki örnekte o ilgilenir beri bunu yapmak için
int main() { 
    Test<bar> b; 
    Test<foo> f; 

    b.go(); // Works! 
    f.go(); // Fails! 
} 
+0

sayesinde ben bile üçüncü versiyonda SFINAE katılan değildi artık sorun T olduğunu görüyoruz' sadece varlığını açıklar Denedim. 'Has_thing' değeri gerçek kodumda bir boole değil - farklı uygulamaların performans özelliklerine göre aynı kodun farklı versiyonlarını seçiyor. – Flexo

0

. go işlevi numaralı bir şablon değil işlevidir, bu nedenle SFINAE hiçbir zaman geçerli olmayabilir. Bunun dışında decltype ile iyi çalışmalısınız (aslında has_thing bayrağına ihtiyacınız yoktur).

Ör. Bu iyi çalışıyor (ve diğer aşırı ile güzel oynar):

template <class U> 
auto go(Test<U> t) 
    -> decltype(U::thing()) { 
    return U::thing(); 
} 
+1

Sorunun üçüncü versiyonu (ki bu uncommented) kesinlikle bir şablon, diğer cevaptan yargılanmakla birlikte SFINE'ye katılmayacağını görebiliyorum. ('Has_thing' bir örnek burada - Gerçek kodda performans özelliklerinin yanı sıra thing' – Flexo

İlgili konular