2011-01-26 28 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 अधिक भार वहाँ वास्तव में foo और bar प्रकार के एक बहुत हैं और call समारोह उनमें से कोई ज्ञान नहीं है के बाद से काम नहीं करता है (मूल रूप से call एक के अंदर है और उपयोगकर्ता अपने स्वयं के प्रकार की आपूर्ति करते हैं)।

मैं सी ++ 0x का उपयोग नहीं कर सकता, और मुझे सभी आधुनिक कंपाइलरों के लिए एक समाधान समाधान की आवश्यकता है।

नोट: similar question का समाधान दुर्भाग्यवश यहां काम नहीं करता है।

+0

बहुत परेशानी की समस्या। मैं भी समाधान जानना चाहता हूं। –

+0

क्या आप उन कार्यों का पता लगाना चाहते हैं जो केवल तत्काल बिंदु पर दिखाई दे रहे हैं? –

+0

@ जोहान्स वास्तव में मेरे मामले में कोई फर्क नहीं पड़ता। तत्काल (फ़ंक्शन टेम्पलेट के) पर, सभी उम्मीदवार फ़ंक्शंस * * ज्ञात होंगे। –

उत्तर

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

एफ() के रिटर्न प्रकारों का त्वरित संशोधन पारंपरिक SFINAE समाधान उत्पन्न करता है।

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

हालांकि, वहाँ गंभीर प्रतिबंध नहीं हैं:

+0

मेरा मानना ​​है कि 'एफ' के अधिभार क्या हैं, समाधान का हिस्सा नहीं है। – aschepler

3

तो boost अनुमति दी है, निम्नलिखित कोड अपने उद्देश्य को पूरा कर सकते हैं।
कोड मानता है कि सभी उपयोगकर्ता कार्यों में हस्ताक्षर (T const&), है इसलिए (T) की अनुमति नहीं है।
उपरोक्त में फ़ंक्शन void f(...) फ़ंक्शन को नि: शुल्क स्थायी फ़ंक्शन होने की आवश्यकता है।
यदि कंपाइलर सामान्य रूप से अपेक्षाकृत दो चरण लुकअप को लागू करता है, तो शायद सभी उपयोगकर्ता फ़ंक्शंस has_f कक्षा टेम्पलेट की परिभाषा से पहले प्रकट होना चाहिए।
ईमानदारी से, मुझे कोड की उपयोगिता पर भरोसा नहीं है, लेकिन फिर भी मुझे उम्मीद है कि इससे मदद मिलती है।

संबंधित मुद्दे