2013-06-15 24 views
10

Bir hafta önce, yalnızca bir sınıf şablonunu yalnızca belirli bir üye işlevine sahip olsaydı nasıl örneklendirebileceğimi soran bir soru sordum. Cevabımda, karmaşık bir çözüm buldum. Ama sonra kendi başıma yapmayı denedim. Ben sadece bu tür bir T türünü anlamaya yetecek kadar 0 parametre alarak f isimli bir fonksiyona sahip olup olmadığını bilmek istedim. this thread?Bu, SFINAE olarak kabul edilir mi?

+2

kullanmak ve evet, bu doğrudur belirleyin. Diğer cevapların neden daha karmaşık olduğuna gelince ... söylemesi zor. –

+0

'Has_f'ın kendisi SFINAE'ye güveniyor,' A' yazmıyor. –

+0

Bir olasılık olarak, bazı derleyicilerde (* öksürük * MSVC2012) bazı derleyicilerde SFINAE desteği, daha karmaşık bir SFINAE'ye sahip olmak için bu karmaşıklığın bir kısmı olabilir. Bir kenara göre, std :: declval () .f() 've' std :: declval () .f() '(veya bu 'std :: declval () .f()'?) Bu özelliğe rvalue referansı nedeniyle C++ 1y'de farklı şeyler olabilir. – Yakk

cevap

7

Yep kadar komplike diğer cevaplar neden

#include <type_traits> 
#include <utility> 

template <typename T, typename = void> 
struct has_f : std::false_type { }; 

template <typename T> 
struct has_f< 
    T, 
    decltype(std::declval<T>().f(), void())> : std::true_type { }; 

template <typename T, typename = typename std::enable_if<has_f<T>::value>::type> 
struct A { }; 

struct B 
{ 
    void f(); 
}; 

struct C { }; 

template class A<B>; // compiles 
template class A<C>; // error: no type named ‘type’ 
        // in ‘struct std::enable_if<false, void>’ 

Eğer öyleyse, sen C++ 11 SFINAE en basit, en deyimsel tarzda bunu çözdük.

Dönüş türünün void olduğunu, nonstatik bir üye olduğunu ve hiçbir parametrenin olmadığını kontrol etmediğinizi unutmayın. f, hiçbir argüman olmadan kolayca çağrılabilir. Bir functor bile olabilir.

, void dönen bir nullary üyesi nonstatic işlev için kontrol Evet, bu SFINAE olduğunu

template <typename T> 
struct has_f<T, decltype(void(static_cast< void (T::*)(void) >(&T::f))) > 
    : std::true_type {}; 

template <typename T> 
struct has_f<T, decltype(void(static_cast< void (T::*)(void) const >(&T::f))) > 
    : std::true_type {}; 
+0

Yani ben dönüş tipi geçersiz olup olmadığını kontrol etmek için std :: result_of 'kullanın? –

+0

@MemyselfandI Bu bir şekilde, 'decltype'ı da kullanabilirsiniz. std :: result_of' std :: bind' ve std :: function' tarafından kullanılan INVOKE konseptini desteklemek için biraz garip bir dans yapar. Birden fazla koşulu bir kerede kontrol etmenin hızlı bir yolu için düzenlememe bakın. Her durumda, ayrıca std :: is_same''e de ihtiyacınız olacak. – Potatoswatter

+0

Sanırım std :: is_same :: value '(parantezin kapanması) ve benzer şekilde aşağıdaki satır için. – hvd

İlgili konular