2011-01-26 32 views
6

Belirli bir sınıf için bir serbest fonksiyonun aşırı yüklenip yüklenmediğini belirlemek için SFINAE kullanarak bir yol var mı?SFINAE: Sınıfın serbest fonksiyonu olup olmadığını tespit edin

Temelde, aşağıdaki çözüm var:

struct has_no_f { }; 

struct has_f { }; 

void f(has_f const& x) { } 

template <typename T> 
enable_if<has_function<T, f>::value, int>::type call(T const&) { 
    std::cout << "has f" << std::endl; 
} 

template <typename T> 
disable_if<has_function<T, f>::value, int>::type call(T const&) { 
    std::cout << "has no f" << std::endl; 
} 

int main() { 
    call(has_no_f()); // "has no f" 
    call(has_f()); // "has f" 
} 

Basitçe orada foo ve bar türde bir çok aslında ve call fonksiyonu bunlardan hiçbir bilgiye sahip olduğundan temelde (çalışmıyor call aşırı call'un içinde bir ve kullanıcılar kendi türlerini tedarik ederler).

C++ 0x kullanamıyorum ve tüm modern derleyiciler için çalışan bir çözüme ihtiyacım var.

Not: similar question'un çözümü ne yazık ki burada çalışmıyor.

+0

Çok zorlayıcı problem. Ben de çözümü bilmek istiyorum. –

+0

Sadece örnekleme noktasında görülebilen işlevleri tespit etmek ister misiniz? –

+0

@Johannes Benim durumumda gerçekten önemli değil. Anlatım noktasında (fonksiyon şablonunun), tüm aday fonksiyonlar * bilinecektir. –

cevap

3
#include <iostream> 
#include <vector> 
#include <algorithm> 
#include <utility> 
#include <functional> 
#include <type_traits> 

struct X {}; 
struct Y {}; 

__int8 f(X x) { return 0; } 
__int16 f(...) { return 0; } 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int8), int>::type call(T const& t) { 
    std::cout << "In call with f available"; 
    f(t); 
    return 0; 
} 

template <typename T> typename std::enable_if<sizeof(f(T())) == sizeof(__int16), int>::type call(T const& t) { 
    std::cout << "In call without f available"; 
    return 0; 
} 

int main() { 
    Y y; X x; 
    call(y); 
    call(x); 
} 

F() dönüş türlerinin hızlı bir şekilde değiştirilmesi, geleneksel SFINAE çözümünü verir.

#include <boost/type_traits.hpp> 
#include <boost/utility/enable_if.hpp> 
using namespace boost; 

// user code 
struct A {}; 
static void f(A const&) {} 
struct B {}; 


// code for has_f 
static void f(...); // this function has to be a free standing one 

template< class T > 
struct has_f { 
    template< class U > 
    static char deduce(U(&)(T const&)); 

    template< class U, class V > 
    static typename disable_if_c< is_same< V, T >::value, char(&)[2] >::type 
    deduce(U(&)(V const&)); 

    static char (&deduce(...))[2]; 

    static bool const value = (1 == sizeof deduce(f)); 
}; 

int main() 
{ 
    cout<< has_f<A>::value <<endl; 
    cout<< has_f<B>::value <<endl; 
} 

Ancak şiddetli kısıtlamalar vardır: boost izin verilir

+0

"f" nin aşırı yüklenmelerinin, çözümün bir parçası değil, algılanması gereken şey olduğuna inanıyorum. – aschepler

3

, aşağıdaki kodu amaçlı karşılamak olabilir.
Kod, tüm kullanıcı işlevlerinin (T const&), imzasına sahip olduğunu varsaydığından (T) ürününe izin verilmez.
Yukarıdaki void f(...) işlevinin serbest duran bir işlevi olması gerektiği görünüyor.
Derleyici, normalde beklendiği gibi iki aşamalı bir denetimi zorlarsa, muhtemelentüm kullanıcı işlevlerinin has_f sınıfı şablon tanımından önce görünmesi gerekir.
Dürüst olmak gerekirse, kodun kullanışlılığından emin değilim, ancak umarım bu, 'un yardımcı olmasını sağlar.

İlgili konular