2011-01-26 45 views
6

有沒有一種方法,使用SFINAE來檢測一個給定的類是否有一個自由函數重載?SFINAE:檢測類是否具有自由功能

基本上,我已經得到了以下解決方案:

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" 
} 

只要超載call不起作用,因爲實際上有很多的foobar類型和call函數沒有他們的知識(基本call是在一個和用戶提供自己的類型)。

我不能使用C++ 0x,我需要一個適用於所有現代編譯器的工作解決方案。

注意:解決方案similar question不幸的是不能在這裏工作。

+0

非常乾淨的問題。我也想知道解決方案。 – 2011-01-26 14:50:57

+0

是否要檢測僅在實例化處可見的函數? – 2011-02-05 10:50:49

回答

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()的返回類型的快速修改產生了傳統的SFINAE解決方案。

3

如果boost是允許的,下面的代碼可能會滿足你的目的:

#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; 
} 

不過,也有嚴格的限制。
該代碼假定所有用戶功能都有簽名(T const&), 因此不允許使用(T)
在上面的函數void f(...)似乎需要一個獨立的 函數。
如果編譯器按預期正常執行兩個階段查找,則可能 所有用戶函數都必須在has_f類 模板的定義之前出現。
老實說,我對代碼的有用性沒有信心,但無論如何,我希望 這有助於。

相關問題