2015-10-30 7 views
26
template <int * ip> struct test {}; 

struct q { 
    static int a; 
    int b; 

    constexpr q(int b_) : b(b_) {} 
}; 

int i; 
constexpr q q0(2); 

int main() 
{ 
    constexpr test<&i> t1;  // Works fine 
    constexpr test<&q::a> t2; // Works 
    constexpr test<&q0.b> t3; // Does not work; address of non-static member? 

    return 0; 
} 

संकलन समय के दौरान ज्ञात टेम्पलेट तर्क &q0.b के बावजूद कोड के उपरोक्त टुकड़े में टी 3 की घोषणा विफल हो जाती है। कुछ Googling है कि इस मानक द्वारा अनुमत नहीं है पता चला (खंड 14.3.2):गैर स्थैतिक सदस्य का पता क्यों टेम्पलेट गैर-प्रकार पैरामीटर के रूप में अनुमति नहीं है?

[Note: Addresses of array elements and names or addresses of non-static class members are not acceptable template-arguments.

X<&s.m> x4; // error: address of non-static membe

तो क्यों वास्तव में यह स्पष्ट रूप से मानक से वैश्विक चर अद्वितीय होने का गैर स्थिर सदस्यों के पते के बावजूद के साथ-साथ की अनुमति नहीं है संकलन समय के दौरान जाना जाता है?

+0

मैंने जीसीसी 5.1.1 और clang 3.5.0 के साथ -std = C++ 11 – nav

+0

कोई '(नया क्यू) -> बी' संकलन समय –

+0

पर ज्ञात नहीं है यह प्रकार' int * ' , यह 'int q :: *' है, है ना? – skypjack

उत्तर

15

सबसे पहले, सबोबजेक्ट्स के पॉइंटर्स/संदर्भों का उपयोग करने के लिए, आपको उन्हें उलझाने में सक्षम होना चाहिए। यह एक बहुत बड़ा उपक्रम है।

दूसरा, और शायद अधिक महत्वपूर्ण बात, N4198 से:

The restriction that the constant expression must name a complete object is retained to avoid aliasing problems with pointers to subobjects:

struct A { int x, y; } a; 
template<int*> struct Z; 
using B = Z<&a.x + 1>; 
using C = Z<&a.y>; 
// Are B and C the same type? 

Richard Smith के शब्दों में,

The answer "yes" is problematic because there are things you can do with a pointer to [ a.y ] that would have undefined behavior if performed on a pointer past the end of [ a.x ] The answer "no" is problematic because they (in typical implementations) represent the same address.

+0

+, संक्षेप में मुख्य कारक। – Columbo

+1

@ टी.सी. क्या हम उसी स्थिति में नहीं चलेंगे, क्या एक्स और वाई स्थैतिक सदस्य या साधारण वैश्विक चर थे?(मैं सी ++ में एक विशेषज्ञ नहीं हूं; मैं बस समझने की कोशिश कर रहा हूं :)) – nav

+0

@ टी.सी. रिचर्ड स्मिथ का आपका उद्धरण अधिक उचित तर्क प्रदान करता है: "ध्यान रखें कि टेम्पलेट पैरामीटर कुछ ऐसा होना चाहिए जिसे संकलित समय पर उचित रूप से निर्धारित किया जा सके और उलझाया जा सके। सामान्य पॉइंटर्स संकलन-समय पर ज्ञात नहीं हैं (रनटाइम लिंकर स्थानांतरित हो सकता है चीजें चारों ओर) और अनिवार्य रूप से स्पष्ट नियम नहीं हैं कि उन्हें सभी प्लेटफार्मों पर कैसे उलझाया जाना चाहिए। " – Thinkeye

1

कोड के इस टुकड़े के साथ अपने मुख्य बदलें

int main(void) 
{  
constexpr static int bb = 5;  
constexpr test<&bb> t;  
return 0; 
} 

और आप करेंगे त्रुटि प्राप्त करें बीबी टेम्पलेट तर्क bec के रूप में उपयोग नहीं किया जा सकता है इस बात का कोई संबंध नहीं है (लिंकर से संबंधित कर्मचारियों के साथ गलत नहीं होना चाहिए)।

क्लास डेटा सदस्यों को तब तक एक्सेस नहीं किया जा सकता जब तक उन्हें ऑब्जेक्ट के माध्यम से संदर्भित नहीं किया जाता है, और टेम्पलेट इंस्टेंटेशन के दौरान खाते में नहीं लिया जा सकता है, क्योंकि डेटा सदस्यों के पास लिंक नहीं है, यानी वे परिभाषित प्रतीक नहीं हैं और इसलिए टेम्पलेट तर्क के रूप में उपयोग नहीं किया जा सकता ।

इसका अर्थ है कि एक readelf आप इस की पुष्टि कर सकते कर रही:

48: 00000000004006ac  4 OBJECT LOCAL DEFAULT 14 q0 


68: 000000000060097c  0 NOTYPE GLOBAL DEFAULT ABS __bss_start 
69: 0000000000600978  4 OBJECT GLOBAL DEFAULT 23 q::a 

लेकिन कोई q0.b परिभाषित किया गया है। वैकल्पिक नाम (मैंगल) नामक किसी भी स्थिर वर्ग के सदस्य होंगे जो भाषा की गतिशील क्षमताओं को पट्टी करेंगे।

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

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