2011-01-26 44 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类 模板的定义之前出现。
老实说,我对代码的有用性没有信心,但无论如何,我希望 这有助于。

相关问题