operator->*()
लेता है दो तर्क:
- वह ऑब्जेक्ट जिस पर चल रहा है।
- सदस्य सूचक लागू किया जाना चाहिए।
यदि सदस्य सूचक केवल डेटा सदस्य के लिए पहुंच है, तो परिणाम सीधे आगे है: आप केवल सदस्य का संदर्भ वापस कर सकते हैं। यदि यह एक फ़ंक्शन है, तो, चीजें थोड़ा अधिक जटिल हैं: सदस्य एक्सेस ऑपरेटर को इसके बजाय कॉल करने योग्य ऑब्जेक्ट को वापस करने की आवश्यकता है। कॉल करने योग्य ऑब्जेक्ट तर्कों की उचित संख्या लेता है और सदस्य सूचक का प्रकार देता है।
मुझे एहसास है कि मूल प्रश्न सी ++ 03 के साथ टैग किया गया है लेकिन "उचित" सी ++ 03 कार्यान्वयन करना एक लंबा लंबा टाइपिंग व्यायाम है: आपको कोड में विविध टेम्पलेट्स द्वारा आसानी से किया जाना होगा प्रत्येक तर्क के लिए नीचे। इसलिए, यह कोड मुख्य रूप से अधिक स्पष्ट रूप से दिखाने के लिए और टाइपिंग अभ्यास के माध्यम से चलने से बचने के लिए सी ++ 11 का उपयोग करता है।
यहाँ एक सरल "स्मार्ट" सूचक operator->*()
को परिभाषित है:
template <typename T>
class my_ptr
{
T* ptr;
public:
my_ptr(T* ptr): ptr(ptr) {}
template <typename R>
R& operator->*(R T::*mem) { return (this->ptr)->*mem; }
template <typename R, typename... Args>
struct callable;
template <typename R, typename... Args>
callable<R, Args...> operator->*(R (T::*mem)(Args...));
};
मैं "उचित" के लिए लगता है का समर्थन यह भी const
संस्करणों को परिभाषित करने की जरूरत है: कि काफी सीधे आगे तो मैं इन को छोड़ते हुए कर रहा हूँ होना चाहिए। मूल रूप से दो संस्करण हैं:
- एक संस्करण एक गैर-फ़ंक्शन सदस्य को पॉइंटर ले रहा है जो केवल दिए गए सूचक के लिए संदर्भित सदस्य को लौटाता है।
- एक संस्करण एक फ़ंक्शन सदस्य को पॉइंटर ले रहा है जो उपयुक्त
callable
ऑब्जेक्ट देता है।callable
में फ़ंक्शन कॉल ऑपरेटर होना आवश्यक है और इसे उचित रूप से लागू करना होगा।
तो, परिभाषित करने के लिए अगली बात callable
प्रकार है: यह वस्तु के लिए एक सूचक और सदस्य के लिए एक सूचक पकड़ और उन्हें कॉल पर लागू होंगे:
#include <utility>
template <typename T>
template <typename R, typename... Args>
struct my_ptr<T>::callable {
T* ptr;
R (T::*mem)(Args...);
callable(T* ptr, R (T::*mem)(Args...)): ptr(ptr), mem(mem) {}
template <typename... A>
R operator()(A... args) const {
return (this->ptr->*this->mem)(std::forward<A>(args)...);
}
};
खैर, कि काफी सीधे है आगे। एक मुश्किल बिट यह तथ्य है कि फंक्शन कॉल ऑपरेटर के तर्कों को तर्क दिया जा रहा है, जो सदस्य के सूचक के मुकाबले अलग-अलग प्रकार के हो सकते हैं। ऊपर दिया गया कोड बस उन्हें अग्रेषित करके स्थिति से संबंधित है।
template <typename T>
template <typename R, typename... Args>
my_ptr<T>::callable<R, Args...> my_ptr<T>::operator->*(R (T::*mem)(Args...)) {
return callable<R, Args...>(this->ptr, mem);
}
ठीक है, बस इतना ही है:
लापता सा ऊपर callable
प्रकार के लिए कारखाने समारोह है! फैंसी सी ++ 11 वैरिएडिक टेम्पलेट्स का उपयोग करके यह काफी कोड है। एक सी ++ 03 को खिलाने के लिए इस सामान को टाइप करना वास्तव में कुछ नहीं है जो मैं चाहता हूं। प्लस तरफ, मैं सोचता हूं ये ऑपरेटर गैर-सदस्य कार्य हो सकते हैं। यही है, उन्हें उपयुक्त नामस्थान में कार्यान्वित किया जा सकता है जिसमें केवल इन ऑपरेटरों का उपयोग होता है और एक खाली टैग-प्रकार होता है जो एक स्मार्ट सूचक प्रकार से प्राप्त होता है। टैग-टैग आधार होने के साथ ऑपरेटर एडीएल के माध्यम से पाए जाएंगे और सभी स्मार्ट पॉइंटर के लिए काम करेंगे। callable
बनाने के लिए आवश्यक पॉइंटर को पकड़ने के लिए वे operator->()
का उपयोग कर सकते हैं।
सी ++ 11 का उपयोग करना यह किसी भी विशिष्ट स्मार्ट सूचक प्रकार से स्वतंत्र operator->*()
के लिए समर्थन को लागू करने के लिए वास्तव में सीधे आगे है। नीचे दिया गया कोड कार्यान्वयन और सरल उपयोग दिखाता है। यह इस तथ्य का उपयोग करता है कि यह संस्करण केवल एडीएल के आधार पर पाया जा सकता है (आपको इसके लिए कोई निर्देश या निर्देश नहीं होना चाहिए) और स्मार्ट पॉइंटर्स शायद operator->()
लागू करते हैं: कोड स्मार्ट पॉइंटर के पॉइंटर को पकड़ने के लिए इस फ़ंक्शन का उपयोग करता है । member_access
नामस्थान शायद अन्य स्मार्ट पॉइंटर्स द्वारा बस एक उपयुक्त शीर्षलेख में जाना चाहिए जो तब member_access::member_acccess_tag
(जो private
(!) बेस क्लास हो सकता है क्योंकि यह अभी भी member_access
में देखने के लिए एडीएल को ट्रिगर करता है)।
#include <utility>
namespace member_access
{
struct member_access_tag {};
template <typename Ptr, typename R, typename T>
R& operator->*(Ptr ptr, R T::*mem) {
return ptr.operator->()->*mem;
}
template <typename R, typename T, typename... Args>
struct callable {
T* ptr;
R (T::*mem)(Args...);
callable(T* ptr, R (T::*mem)(Args...)): ptr(ptr), mem(mem) {}
template <typename... A>
R operator()(A... args) const {
return (this->ptr->*this->mem)(std::forward<A>(args)...);
}
};
template <typename Ptr, typename R, typename T, typename... Args>
callable<R, T, Args...> operator->*(Ptr ptr, R (T::*mem)(Args...)) {
return callable<R, T, Args...>(ptr.operator->(), mem);
}
}
template <typename T>
class my_ptr
: private member_access::member_access_tag
{
T* ptr;
public:
my_ptr(T* ptr): ptr(ptr) {}
T* operator->() { return this->ptr; }
};
@OP के लिए: [यहां एक पेपर] (http://aristeia.com/Papers/DDJ_Oct_1999.pdf) जो ** ** ** जो आप चाहते हैं उसका वर्णन करता है। –
"सूचक-से-सदस्य ऑपरेटरों '-> *' और '। *' "को धारा 5.5 में सी ++ 11 मानक में वर्णित किया गया है। वे सी ++ में मौजूद हैं, भले ही उनका उपयोग आमतौर पर नहीं किया जाता है। –
सी ++ एफएक्यू के माध्यम से सदस्य के लिए सूचक: http://www.parashift.com/c++-faq/dotstar-vs-arrowstar.html –