2012-01-06 8 views
8

मैं परीक्षण करने के लिए एक हैक के साथ आने का प्रयास कर रहा था अगर std::isnan प्रीप्रोसेसर में विशेष आवरण कंपाइलर के बिना परिभाषित किया गया है, और निम्न के साथ आया, जिसे मैं ठीक काम करने की उम्मीद कर रहा था।SFINAE किसी अन्य नामस्थान से मुक्त फ़ंक्शन का परीक्षण करने के लिए

#include <cmath> 
#include <type_traits> 

namespace detail { 
    using namespace std; 

    struct dummy {}; 
    void isnan(dummy); 

    //bool isnan(float); // Just adding this declaration makes it work! 

    template <typename T> 
    struct is_isnan_available { 
     template <typename T1> 
     static decltype(isnan(T1())) test(int); 
     template <typename> 
     static void test(...); 

     enum { value = !std::is_void<decltype(test<T>(0))>::value }; 
    }; 
} 

int main() { 
    return detail::is_isnan_available<float>::value; 
} 

it doesn't detect it बाहर निकलता है। मुझे पता है कि कुछ std::isnan को विचारधारा पर परिभाषित किया गया है, क्योंकि मैंने मैन्युअल रूप से परीक्षण किया था।

और जब मैं uncomment the marked line above, यह काम करता है।

मुझे यहां क्या याद आ रही है? इस व्यवहार को क्या समझाता है?

+0

उत्सुक: is_isnan_available :: मूल्य कार्य? –

+0

@ टोनी: 'std :: isnan' दोनों के लिए अधिभारित है। और फिर भी, फ्लोट से डबल तक एक अंतर्निहित रूपांतरण है। फिर भी, मैंने कोशिश की और डबल के लिए परीक्षण या तो काम नहीं करता है। –

+0

@ टोनीडेलॉय: अच्छा विचार, हालांकि मानक कार्यों को आम तौर पर अधिभारित किया जाता है। इसके बावजूद, आप यह जांच सकते हैं कि यह अभी भी [ideone] (http://www.ideone.com/U7EqO) पर काम नहीं करता है –

उत्तर

7

बात यह है कि उपयोग निर्देश वर्तमान नामस्थान में सदस्यों को नहीं जोड़ता है, इसलिए std:: सदस्य अभी भी इस नामस्थान में घोषणाओं से छिपाए जा सकते हैं।

using std::isnan इसके बजाय व्यवहार करेगा क्योंकि आयातित नामस्थान के सदस्यों को use - स्थान और आयातित नामस्थान दोनों नामांकन नामस्थान में जोड़ा गया था। उपयोग घोषणा नामस्थान में एक सामान्य घोषणा है, इसलिए अनुवर्ती घोषणाओं के साथ ओवरलोड रिज़ॉल्यूशन में भाग ले सकते हैं।

हालांकि, टिप्पणियों में बताया गया है कि यदि कार्य मौजूद नहीं है तो त्रुटि उत्पन्न होगी। इसके आसपास काम करने के लिए आपको put it out of your detail:: namespace then की आवश्यकता है। यह काम करना चाहिए, क्योंकि आयातित परिभाषा dummy अधिभार के समान स्तर पर होगी। आप ओवरलोड को वैश्विक नेमस्पेस पर ले जा सकते हैं, या आप एक सहायक नेमस्पेस (वैश्विक नामस्थान में) और import both बना सकते हैं।

+0

यदि यह अस्तित्व में नहीं है तो यह एक कठिन त्रुटि का कारण बन जाएगा। http://www.ideone.com/44sE3। मेरे पास 'नेमस्पेस' का उपयोग करना है क्योंकि अगर मैं उम्मीद नहीं कर रहा हूं कि मैं अस्तित्व में नहीं हूं तो मैं फ़ंक्शन का नाम नहीं दे सकता। –

+0

क्या आप बता सकते हैं कि नाम लुकअप के संदर्भ में, उन दोनों के बीच क्या अंतर है? सहजता से मैंने सोचा कि 'नेमस्पेस का उपयोग करना' एक ही समय में सभी प्रतीकों को आयात करने के लिए एक शॉर्टकट था, मुझे निश्चित रूप से नाम लुकअप की अवधि में विसंगतियों की उम्मीद नहीं थी। –

+0

आह, यह है! मुझे नहीं पता था कि मैं इसके साथ 'std' से घोषणा छिपाऊंगा। धन्यवाद। –

1

मैंने इस समस्या को पॉज़िक्स थ्रेड-सुरक्षित एपीआई के सेट के लिए हल किया जो गैर-थ्रेड-सुरक्षित मानक फ़ंक्शन का समर्थन करता है: C++11 alternative to localtime_r। यह कोड पता लगाता है कि क्या एक एपीआई को वैश्विक नामस्थान में परिभाषित किया गया है, और यदि यह अस्तित्व में नहीं है, तो कस्टम वर्कअराउंड का चयन करता है।

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

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