2011-01-26 33 views
6

Có cách nào, sử dụng SFINAE, để phát hiện xem chức năng miễn phí có bị quá tải cho một lớp nhất định không?SFINAE: phát hiện xem lớp học có chức năng miễn phí không

Về cơ bản, tôi đã có những giải pháp sau đây:

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

Đơn giản chỉ cần quá tải call không hoạt động kể từ khi có thực sự là rất nhiều foobar loại và call chức năng không có kiến ​​thức của họ (về cơ bản call là bên trong một và người dùng cung cấp các loại riêng của họ).

Tôi không thể sử dụng C++ 0x và tôi cần giải pháp làm việc cho tất cả các trình biên dịch hiện đại.

Lưu ý: giải pháp cho một sự kiện similar question không hoạt động ở đây.

+0

vấn đề rất quan trọng. Tôi cũng muốn biết giải pháp. –

+0

Bạn có muốn phát hiện các chức năng chỉ hiển thị tại thời điểm khởi tạo không? –

+0

@Johannes Thực sự không quan trọng trong trường hợp của tôi. Tại điểm khởi tạo (của mẫu hàm), tất cả các hàm ứng viên * sẽ * được biết. –

Trả lời

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

Sửa đổi nhanh kiểu trả về của f() mang lại giải pháp SFINAE truyền thống.

+0

Tôi tin rằng sự quá tải của 'f' là những gì được phát hiện, không phải là một phần của giải pháp. – aschepler

3

Nếu boost được cho phép, các mã sau đây có thể đáp ứng mục đích của bạn:

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

Tuy nhiên, có những hạn chế nghiêm trọng.
Mã này giả định rằng tất cả các chức năng của người dùng có chữ ký (T const&), vì vậy (T) không được phép.
Chức năng void f(...) ở trên dường như cần phải có chức năng đứng miễn phí .
Nếu trình biên dịch thực thi hai giai đoạn tra cứu như mong đợi bình thường, có lẽ tất cả các chức năng của người dùng phải xuất hiện trước định nghĩa của mẫu has_f lớp .
Thành thật mà nói, tôi không tự tin về tính hữu ích của mã, nhưng dù sao tôi hy vọng điều này sẽ giúp ích cho bạn.

Các vấn đề liên quan