2012-03-28 4 views
13

हमारे कुख्यात litb के पास how to circumvent the access check पर एक दिलचस्प लेख है।सदस्यों के सूचक को सदस्य के पहुंच स्तर को बाधित कर सकते हैं?

यह पूरी तरह से इस सरल कोड द्वारा दर्शाया गया है:

#include <iostream> 

template<typename Tag, typename Tag::type M> 
struct Rob { 
    friend typename Tag::type get(Tag) { 
    return M; 
    } 
}; 

// use 
struct A { 
    A(int a):a(a) { } 
private: 
    int a; 
}; 

// tag used to access A::a 
struct A_f { 
    typedef int A::*type; 
    friend type get(A_f); 
}; 

template struct Rob<A_f, &A::a>; 

int main() { 
    A a(42); 
    std::cout << "proof: " << a.*get(A_f()) << std::endl; 
} 

कौन सा संकलित करता है तथा रन (उत्पादन 42) gcc 4.3.4, gcc 4.5.1, जीसीसी 4.7.0 (user1131467 की टिप्पणी देखें) और बजना 3.0 और Comeau सी के साथ संकलित साथ/सी सी ++ 03 सख्त मोड में ++ 4.3.10.1 और MSVC 2005

मैं this answer जिसमें मैं इसका इस्तेमाल सही ठहराने के लिए कि यह वास्तव में कानूनी था पर Luchian द्वारा कहा गया था। मैं लुचियान से सहमत हूं कि यह अजीब है, हालांकि क्लेंग और कॉमऊ दोनों "मानक" कंपाइलर्स के लिए करीबी दावेदार हैं (डिफ़ॉल्ट रूप से एमएसवीसी से कहीं ज्यादा) ...

और मुझे ड्राफ्ट में कुछ भी नहीं मिला मेरे द्वारा उपलब्ध मानकों में से (n3337 अंतिम संस्करण है जिस पर मुझे अपना हाथ मिला है)।

तो ... क्या कोई वास्तव में यह मानता है कि यह कानूनी है या नहीं है?

+0

एफवाईआई यह 'सब + आउटपुट: 42' 'जी ++ - 4.7 (डेबियन 4.7.0-1) 4.7.0' के साथ' -std = C++ 11' और '-std = gnu ++ 11' –

+0

दोनों में आउटपुट करता है क्षमा करें, यह मेरा बुरा है। यह संकलित करता है, जो संकलित नहीं किया गया था http://stackoverflow.com/a/6886432/673730 - और मैं डेटा सदस्य नहीं, एक निजी फ़ंक्शन तक पहुंचने का प्रयास कर रहा था। –

+0

बीटीडब्ल्यू मैं अभी भी इसका जवाब ढूंढ रहा हूं, अगर जवाब काम करता है, तो यह वही होगा जो मैं खोज रहा था, लेकिन ऐसा नहीं है। –

उत्तर

13

हां, यह कानूनी है। प्रासंगिक पाठ §14.7.2/12 पर है, स्पष्ट टेम्पलेट इन्स्टेन्शियशन बारे में बात कर:

12 सामान्य पहुँच जाँच नियम स्पष्ट instantiations निर्दिष्ट करने के लिए उपयोग होने वाले नाम पर लागू नहीं हैं । [नोट: विशेष रूप से, फ़ंक्शन घोषणाकर्ता (पैरामीटर प्रकार, रिटर्न प्रकार और अपवाद विनिर्देशों सहित) में उपयोग किए गए टेम्पलेट तर्क और नाम निजी प्रकार या ऑब्जेक्ट्स हो सकते हैं जो आमतौर पर पहुंच योग्य नहीं होंगे और टेम्पलेट सदस्य टेम्पलेट हो सकता है या सदस्य फ़ंक्शन जो आमतौर पर पहुंच योग्य नहीं होगा। - अंत नोट]

एम्पासिस खान।

+4

आह! शायद यह है कि मुझे कुछ के बारे में व्यापक दृष्टिकोण रखने के लिए मानक के बारे में सबसे ज्यादा पसंद है, आपको बस पूरी चीज से गुजरने और टुकड़ों को टुकड़े करने की जरूरत है। –

+1

@MatthieuM .: लेकिन यही कारण है कि मैं मानक से नफरत करता हूं! :) संपादित करें: हुओश! – GManNickG

+0

यह विडंबनापूर्ण था;) हालांकि अब यह गिटूब पर है, शायद हम जेम्स के इस अनुच्छेद को पार करने के लिए एक संपादन का प्रस्ताव दे सकते हैं! –

5

कोड स्पष्ट रूप से अवैध है (और एक संकलन समय निदान की आवश्यकता है)। लाइन में:

template struct Rob<A_f, &A::a>; 

अभिव्यक्ति A::aA के एक निजी सदस्य तक पहुँचता है।

मानक इस बारे में बहुत स्पष्ट है: “ अभिगम नियंत्रण लिए आवेदन किया है समान रूप से सभी नाम, चाहे नाम घोषणाओं या भाव से भेजा जाता है। “ (§11/4, जोर जोड़ा गया)। चूंकि aA में एक निजी नाम है, A के बाहर इसका कोई भी संदर्भ अवैध है।

+3

यह वास्तव में गैरकानूनी नहीं है, स्पष्ट टेम्पलेट तत्काल के लिए बाद में एक अपवाद जोड़ा गया है। "सब" स्पष्ट रूप से भ्रामक है, यह "सब कुछ है, जब तक अन्यथा निर्दिष्ट नहीं किया गया"। मैं कम नहीं करूँगा क्योंकि यह काफी अनजान है। – GManNickG

+0

@GManNickG वास्तव में, यह स्पष्ट नहीं है, और मुझे लगता है कि एक डीआर क्रम में है। मानक में, "सभी" का मतलब है "सभी", "सभी", अन्यथा निर्दिष्ट नहीं किए जाने तक " और §14.7.2 में संदर्भ अन्य व्याख्याओं की अनुमति दे सकता है (हालांकि वे बहुत स्वाभाविक नहीं हैं)। यह एक विरोधाभास की तरह दिखता है, जिसका अर्थ है कि एक डीआर क्रम में है। –

+0

आप सही हैं, वहां होने वाली योग्यता की कोई आवश्यकता नहीं है। – GManNickG

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