अपडेट: C ++ 11 में, std::addressof
इसके बजाय कोई भी उपयोग कर सकता है boost::addressof
।
आइए पहले हम बूस्ट से कोड कॉपी करते हैं, बिट्स के आसपास कंपाइलर काम करते हैं:
template<class T>
struct addr_impl_ref
{
T & v_;
inline addr_impl_ref( T & v ): v_( v ) {}
inline operator T& () const { return v_; }
private:
addr_impl_ref & operator=(const addr_impl_ref &);
};
template<class T>
struct addressof_impl
{
static inline T * f( T & v, long ) {
return reinterpret_cast<T*>(
&const_cast<char&>(reinterpret_cast<const volatile char &>(v)));
}
static inline T * f( T * v, int ) { return v; }
};
template<class T>
T * addressof( T & v ) {
return addressof_impl<T>::f( addr_impl_ref<T>( v ), 0 );
}
यदि हम फ़ंक्शन का संदर्भ देते हैं तो क्या होता है ?
नोट: addressof
कार्य करने के लिए एक सूचक के साथ उपयोग नहीं किया जा सकता है
C ++ में अगर void func();
घोषित किया गया है, तो func
एक फ़ंक्शन का संदर्भ है जिसमें कोई तर्क नहीं है और कोई परिणाम नहीं लौटाता है। एक फ़ंक्शन का यह संदर्भ तुच्छ रूप से कार्य करने के लिए एक पॉइंटर में बदल सकता है - से @Konstantin
: 13.3.3.2 के अनुसार दोनों T &
औरT *
कार्यों के लिए अप्रभेद्य हैं। पहला एक पहचान रूपांतरण है और दूसरा एक "सटीक मिलान" रैंक (13.3.3.1.1 तालिका 9) वाले फ़ंक्शन-टू-पॉइंटर रूपांतरण है।
समारोह के संदर्भ के माध्यम से पारित addr_impl_ref
, के चुनाव के लिए अधिभार संकल्प में एक अस्पष्टता नहीं है f
, जो डमी तर्क करने के लिए धन्यवाद हल किया जाता है 0
, जो एक है int
पहली और एक करने के लिए प्रोत्साहित किया जा सकता है long
(इंटीग्रल रूपांतरण)।
इस प्रकार हम केवल पॉइंटर लौटाते हैं।
यदि हम रूपांतरण ऑपरेटर के साथ एक प्रकार पास करते हैं तो क्या होगा?
यदि रूपांतरण ऑपरेटर पैदावार करता है T*
तो हमारे पास एक अस्पष्टता है: f(T&,long)
दूसरे तर्क के लिए एक इंटीग्रल प्रमोशन की आवश्यकता होती है जबकि f(T*,int)
रूपांतरण ऑपरेटर को पहली बार बुलाया जाता है (@litb के लिए धन्यवाद)
ऐसा तब होता है जब addr_impl_ref
C ++ मानक कहता है कि रूपांतरण अनुक्रम में एक उपयोगकर्ता द्वारा परिभाषित रूपांतरण हो सकता है। addr_impl_ref
पहले से ही रूपांतरण अनुक्रम के उपयोग को टाइप करने के लिए मजबूर करने के लिए, हम किसी भी रूपांतरण ऑपरेटर को "अक्षम" करते हैं जो कि प्रकार के साथ आता है।
इस प्रकार f(T&,long)
अधिभार का चयन किया जाता है (और इंटीग्रल प्रोमोशन का प्रदर्शन)।
किसी अन्य प्रकार के लिए क्या होता है?
इस प्रकार f(T&,long)
अधिभार का चयन किया जाता है, क्योंकि वहाँ प्रकार मेल नहीं खाता हैT*
पैरामीटर पैरामीटर से ।
नोट: बोरलैंड संगतता के बारे में फाइल में टिप्पणी से, सरणियों संकेत करने के लिए क्षय नहीं है, लेकिन संदर्भ द्वारा पारित कर रहे हैं।
इस अधिभार में क्या होता है?
हम operator&
प्रकार पर लागू होने से बचना चाहते हैं , क्योंकि यह अतिभारित हो सकता है।
reinterpret_cast
इस काम के लिए इस्तेमाल की जा सकने वाली मानक गारंटी (देखें @ माटेयो इटालिया का जवाब: 5.2.10 / 10)।
बूस्टर कंपाइलर चेतावनियों से बचने के लिए (और उन्हें हटाने के लिए ठीक से उपयोग करता है) के साथ कुछ बारीकियों const
और volatile
क्वालिफायर जोड़ता है const_cast
।
- कास्ट
T&
कियाchar const volatile&
- पट्टी
const
औरvolatile
&
पता लेने के लिए ऑपरेटर को आवेदन करें
- कास्ट वापस करने के लिए
T*
const
/ volatile
करतब दिखाने काला जादू का एक सा है, लेकिन यह (बजाय 4 भार के प्रदान करने की तुलना में) काम सरल बना देता है। ध्यान दें कि चूंकि T
अयोग्य है, अगर हम पास करते हैं ghost const&
, तो T*
हैghost const*
इस प्रकार क्वालिफायर वास्तव में खो नहीं किया गया है,।
EDIT: पॉइंटर ओवरलोड का उपयोग पॉइंटर से फ़ंक्शंस के लिए किया जाता है, मैंने उपरोक्त स्पष्टीकरण में कुछ संशोधन किया है। मुझे अभी भी समझ नहीं आया कि यह क्यों जरूरी है।
निम्न आइडोन आउटपुट इसे कुछ हद तक समेटता है ।