जब अतिरिक्त कोष्ठक का प्रभाव पड़ता है, तो ऑपरेटर पूर्वता के अलावा अन्य


91

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

5.1 प्राथमिक भाव [expr.prim]

5.1.1 सामान्य [expr.prim.general]

6 एक संक्षिप्त अभिव्यक्ति एक प्राथमिक अभिव्यक्ति है जिसका प्रकार और मूल्य संलग्न अभिव्यक्ति के समान हैं। कोष्ठक की उपस्थिति प्रभावित नहीं करती है कि क्या अभिव्यक्ति एक अंतराल है। कोष्ठक की अभिव्यक्ति का उपयोग ठीक उसी संदर्भ में किया जा सकता है, जैसे कि संलग्न अभिव्यक्ति का उपयोग किया जा सकता है, और उसी अर्थ के साथ, जैसा कि अन्यथा इंगित किया गया है

प्रश्न : किस संदर्भ में अतिरिक्त कोष्ठक मूल संचालक पूर्वता को ओवरराइड करने के अलावा C ++ प्रोग्राम का अर्थ बदल देते हैं?

नोट : मैं पॉइंटर-टू-मेंबर सिंटैक्स के प्रतिबंध को &qualified-idबिना दायरे के बाहर होना मानता हूं क्योंकि यह अलग-अलग अर्थों के साथ दो सिंटैक्स की अनुमति देने के बजाय सिंटैक्स को प्रतिबंधित करता है । इसी तरह, प्रीप्रोसेसर मैक्रो परिभाषाओं के अंदर कोष्ठकों का उपयोग भी अवांछित संचालक पूर्वता के खिलाफ सुरक्षा करता है।


"मैं सूचक-से-सदस्य के लिए (योग्य-आईडी) रिज़ॉल्यूशन को ऑपरेटर की पूर्ववर्तीता का एक अनुप्रयोग मानता हूं।" -- ऐसा क्यों है? यदि आप कोष्ठक को छोड़ देते हैं &(C::f), का संचालन &अभी भी है C::f, है ना?

@hvd expr.unary.op/4: एक पॉइंटर का सदस्य तभी बनता है जब किसी स्पष्ट &का उपयोग किया जाता है और उसका ऑपरेंड एक योग्य आईडी होता है जो कोष्ठक में संलग्न नहीं होता है।
टेम्प्लेक्स

ठीक है, तो ऑपरेटर की पूर्वता के साथ क्या करना है? (कोई बात नहीं, आपका संपादित प्रश्न

@hvd ने अपडेट किया, मैं इस Q & A में LHS के साथ RHS को भ्रमित कर रहा था , और वहां परर्स का उपयोग ()पॉइंटर-टू-मेंबर सेलेक्टर पर होने वाले फंक्शन कॉल की पूर्ववर्ती स्थिति को ओवरराइड करने के लिए किया जाता है::*
TemplateRex

1
मुझे लगता है कि आपको थोड़ा और सटीक होना चाहिए जिसके बारे में विचार करने की आवश्यकता है। उदाहरण के लिए, एक सी-स्टाइल कास्ट ऑपरेटर (जो भी संदर्भ) बनाने के लिए एक प्रकार के नाम के आसपास कोष्ठक बिल्कुल भी एक कोष्ठक अभिव्यक्ति नहीं बनाते हैं। दूसरी ओर मैं तकनीकी रूप से कह सकते हैं कि हालत के बाद अगर या , जबकि एक parenthesised अभिव्यक्ति है, लेकिन जब से कोष्ठकों वाक्य रचना का हिस्सा हैं यहाँ वे नहीं माना जाना चाहिए। और ना ही IMO का कोई भी मामला होना चाहिए, जहाँ कोष्ठक के बिना अभिव्यक्ति को अब एक इकाई के रूप में पार्स नहीं किया जाएगा, चाहे ऑपरेटर पूर्वता शामिल हो या नहीं।
मार्क वैन लीउवेन

जवाबों:


112

टी एल; डॉ

अतिरिक्त संदर्भों में C ++ प्रोग्राम का अर्थ बदल जाता है:

  • तर्क-निर्भर नाम लुकअप को रोकना
  • सूची संदर्भों में अल्पविराम ऑपरेटर को सक्षम करना
  • अस्पष्ट पार्स के अस्पष्टता संकल्प
  • decltypeभावों में समर्पण भाव
  • प्रीप्रोसेसर मैक्रो त्रुटियों को रोकना

तर्क-निर्भर नाम लुकअप को रोकना

जैसा कि मानक के अनुलग्नक ए में विस्तृत है, post-fix expressionप्रपत्र (expression)का एक है primary expression, लेकिन नहीं id-expression, और इसलिए नहीं unqualified-id। इसका अर्थ यह है कि तर्क-निर्भर नाम लुकअप को (fun)(arg)पारंपरिक रूप की तुलना में फ़ॉर्म के फ़ंक्शन कॉल में रोका जाता है fun(arg)

३.४.२ तर्क-आश्रित नाम देखने के लिए [basic.lookup.argdep]

1 जब एक फ़ंक्शन कॉल में पोस्टफ़िक्स-एक्सप्रेशन (5.2.2) एक अयोग्य-आईडी है , तो अन्य नामस्थानों को सामान्य अयोग्य लुकअप (3.4.1) के दौरान नहीं माना जा सकता है और उन नेमस्पेस, नेमस्पेस-स्कोप फ्रेंड फंक्शन या फ़ंक्शन टेम्पलेट घोषणाएं (11.3) अन्यथा दिखाई नहीं दे सकती हैं। खोज के लिए ये संशोधन तर्कों के प्रकार पर निर्भर करते हैं (और टेम्पलेट टेम्पलेट तर्क के लिए, टेम्पलेट तर्क के नाम स्थान)। [ उदाहरण:

namespace N {
    struct S { };
    void f(S);
}

void g() {
    N::S s;
    f(s);   // OK: calls N::f
    (f)(s); // error: N::f not considered; parentheses
            // prevent argument-dependent lookup
}

उदाहरण का]

सूची संदर्भों में अल्पविराम ऑपरेटर को सक्षम करना

अल्पविराम ऑपरेटर का अधिकांश सूची-जैसे संदर्भों (फ़ंक्शन और टेम्प्लेट तर्क, आरम्भक सूची आदि) में एक विशेष अर्थ है। a, (b, c), dऐसे संदर्भों में प्रपत्र के कोष्ठक नियमित रूप की तुलना में अल्पविराम ऑपरेटर को सक्षम कर सकते हैं a, b, c, dजहाँ अल्पविराम लागू नहीं होता है।

5.18 कोमा ऑपरेटर [expr.comma]

2 संदर्भों में जहां अल्पविराम को एक विशेष अर्थ दिया जाता है, [उदाहरण: कार्यों की दलीलों की सूची (5.2.2) और आरंभिकों की सूची (8.5) - उदाहरण के रूप में] खंड 5 में वर्णित अल्पविराम ऑपरेटर केवल कोष्ठक में दिखाई दे सकता है। [ उदाहरण:

f(a, (t=3, t+2), c);

तीन तर्क हैं, जिनमें से दूसरे का मूल्य 5. उदाहरण है]

पार्सिंग वेर्सेस का एंबीगुएटी रिज़ॉल्यूशन

सी और इसके आर्कन फंक्शन डिक्लेरेशन सिंटैक्स के साथ बैकवर्ड कम्पेटिबिलिटी, आश्चर्यजनक पार्सिंग अस्पष्टता को जन्म दे सकती है, जिसे वेक्सिंग वेर्सेस कहा जाता है। अनिवार्य रूप से, किसी भी चीज़ को घोषणा के रूप में पार्स किया जा सकता है , भले ही एक प्रतिस्पर्धी पार्स भी लागू होगा।

६.६ एम्बिगुएटी रिज़ॉल्यूशन [stmt.ambig]

1 व्याकरण में अभिव्यक्ति-कथनों और घोषणाओं को लेकर एक अस्पष्टता है : एक कार्य-शैली स्पष्ट प्रकार के रूपांतरण (5.2.3) के साथ एक अभिव्यक्ति-कथन, जैसा कि इसके सबसे उप-उपप्रकार एक घोषणा से अप्रभेद्य हो सकता है, जहां पहला घोषणाकर्ता एक के साथ शुरू होता है ( । उन मामलों में बयान एक घोषणा है

.२ अस्पष्टता संकल्प [dcl.ambig.res]

1 एक फंक्शन-स्टाइल कास्ट और 6.8 में उल्लिखित घोषणा के बीच समानता से उत्पन्न अस्पष्टता भी एक घोषणा के संदर्भ में हो सकती है । उस संदर्भ में, विकल्प एक फ़ंक्शन घोषणा के बीच है, जिसमें पैरामीटर नाम के आसपास कोष्ठक के एक निरर्थक सेट और एक स्टाइल-स्टाइल के साथ ऑब्जेक्ट घोषणा को आरम्भक के रूप में रखा गया है। जैसा कि 6.8 में उल्लिखित अस्पष्टताओं के लिए है, संकल्प किसी भी निर्माण पर विचार करना है जो संभवतः एक घोषणा पत्र हो सकता है । [नोट: एक घोषणा को गैर-विचलन शैली के कलाकारों द्वारा स्पष्ट रूप से अस्वीकार किया जा सकता है, = आरंभिकता को इंगित करने के लिए या पैरामीटर नाम के आसपास निरर्थक कोष्ठक को हटाकर। ध्यान दें] [उदाहरण:

struct S {
    S(int);
};

void foo(double a) {
    S w(int(a));  // function declaration
    S x(int());   // function declaration
    S y((int)a);  // object declaration
    S z = int(a); // object declaration
}

उदाहरण का]

इसका सबसे प्रसिद्ध उदाहरण मोस्ट वैक्सिंग पार्स है , जिसका नाम स्कॉट मेयर्स ने अपने प्रभावी एससीएल के आइटम 6 में प्रचलित किया है :

ifstream dataFile("ints.dat");
list<int> data(istream_iterator<int>(dataFile), // warning! this doesn't do
               istream_iterator<int>());        // what you think it does

यह एक फ़ंक्शन की घोषणा करता है data, जिसका रिटर्न प्रकार है list<int>। फ़ंक्शन डेटा दो पैरामीटर लेता है:

  • पहला पैरामीटर नाम है dataFile। यह टाइप है istream_iterator<int>। चारों ओर के कोष्ठक dataFileअतिसुंदर हैं और उन्हें अनदेखा किया जाता है।
  • दूसरे पैरामीटर का कोई नाम नहीं है। इसका प्रकार कुछ भी नहीं लेने और वापस लौटने के लिए सूचक है istream_iterator<int>

पहले फ़ंक्शन तर्क के आसपास अतिरिक्त कोष्ठक रखने (दूसरे तर्क के आसपास कोष्ठक अवैध हैं) अस्पष्टता को हल करेगा

list<int> data((istream_iterator<int>(dataFile)), // note new parens
                istream_iterator<int>());          // around first argument
                                                  // to list's constructor

C ++ 11 में ब्रेस-इनिशियलाइज़र सिंटैक्स है जो कई संदर्भों में इस तरह की पार्सिंग समस्याओं को साइड-स्टेप करने की अनुमति देता है।

भावों में समर्पण decltypeभाव

autoप्रकार में कटौती के विपरीत , decltypeरेफ़ेक्नेसिटी (लवल्यू और रेवल्यू संदर्भ) को कम करने की अनुमति देता है। नियम decltype(e)और decltype((e))अभिव्यक्ति के बीच अंतर करते हैं:

7.1.6.2 सरल प्रकार विनिर्देशक [dcl.type.simple]

4 एक अभिव्यक्ति के लिए e, द्वारा दर्शाया गयाdecltype(e) प्रकार निम्नानुसार परिभाषित किया गया है:

- यदि eएक अनिर्दिष्ट आईडी-एक्सप्रेशन या एक अनिर्धारित क्लास मेंबर एक्सेस (5.2.5) है, decltype(e)तो इसके द्वारा होने वाली इकाई का प्रकार है e। यदि ऐसी कोई इकाई नहीं है, या यदि eओवरलोड कार्यों का एक सेट नाम है, तो कार्यक्रम बीमार है;

- अन्यथा, अगर eएक xvalue है, decltype(e)है T&&, जहां Tका प्रकार है e;

- अन्यथा, यदि eएक लैवल्यू है, decltype(e)तो T&, Tप्रकार कहां है e;

- अन्यथा, decltype(e)का प्रकार है e

डिक्लेयर स्पेसिफिक का ऑपरेंड एक अनवैलिडेटेड ऑपरेंड (क्लॉज 5) है। [ उदाहरण:

const int&& foo();
int i;
struct A { double x; };
const A* a = new A();
decltype(foo()) x1 = 0;   // type is const int&&
decltype(i) x2;           // type is int
decltype(a->x) x3;        // type is double
decltype((a->x)) x4 = x3; // type is const double&

उदाहरण उदाहरण] [नोट: शामिल प्रकार के निर्धारण के नियम decltype(auto)7.1.6.4 में निर्दिष्ट हैं। ध्यान दें]

decltype(auto)प्रारंभिक अभिव्यक्ति के आरएचएस में अतिरिक्त कोष्ठक के लिए समान अर्थ के नियम हैं । यहां C ++ FAQ और इससे संबंधित Q & A से एक उदाहरण दिया गया है

decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; }  //A
decltype(auto) look_up_a_string_2() { auto str = lookup1(); return(str); } //B

पहला रिटर्न string, दूसरा रिटर्न string &, जो स्थानीय चर का संदर्भ है str

प्रीप्रोसेसर मैक्रो संबंधित त्रुटियों को रोकना

सी + + भाषा के साथ उनकी बातचीत में प्रीप्रोसेसर मैक्रोज़ के साथ सूक्ष्मताओं की एक मेजबान है, जिनमें से सबसे आम नीचे सूचीबद्ध हैं

  • मैक्रो परिभाषा में किसी एक मैक्रो मापदंडों के आसपास कोष्ठकों का उपयोग #define TIMES(A, B) (A) * (B);क्रम में अवांछित ऑपरेटर पूर्वता से बचने के लिए (में जैसे TIMES(1 + 2, 2 + 1)जो 9 पैदावार लेकिन चारों ओर कोष्ठकों 6 प्राप्त होते हैं (A)और(B)
  • सम्‍मिलित तर्कों के चारों ओर कोष्ठक का उपयोग अंदर करना: assert((std::is_same<int, int>::value));जो अन्यथा संकलित नहीं होगा
  • शामिल हेडर में मैक्रो के विस्तार से बचाने के लिए एक फ़ंक्शन के आसपास कोष्ठक का उपयोग करना: (min)(a, b)(ADL को अक्षम करने के अवांछित दुष्प्रभाव के साथ)

7
वास्तव में कार्यक्रम का अर्थ नहीं बदलता है, लेकिन सबसे अच्छा अभ्यास और संकलक द्वारा उत्सर्जित चेतावनियों को प्रभावित करता है: अतिरिक्त कोष्ठक का उपयोग किया जाना चाहिए if/ whileयदि अभिव्यक्ति एक असाइनमेंट है। जैसे if (a = b)- चेतावनी (क्या आपका मतलब है ==?), जबकि if ((a = b))- कोई चेतावनी नहीं।
Csq

@ सीसी धन्यवाद, अच्छा अवलोकन, लेकिन यह एक विशेष संकलक द्वारा चेतावनी है और मानक द्वारा अनिवार्य नहीं है। मुझे नहीं लगता कि इस प्रश्नोत्तर की भाषा-वकील प्रकृति के भीतर फिट बैठता है।
TemplateRex

क्या (min)(a, b)(बुराई के साथ MACRO min(A, B)) तर्क-निर्भर नाम देखने की रोकथाम का हिस्सा है?
Jarod42

@ Jarod42 मुझे ऐसा लगता है, लेकिन आइए इस तरह के और अन्य बुरे मैक्रों पर सवाल के दायरे से बाहर होने पर विचार करें :-)
TemplateRex

5
@JamesKanze: ध्यान दें कि ओपी और टेम्प्लेट एक ही व्यक्ति हैं ^ _ ^
Jarod42

4

सामान्य तौर पर, प्रोग्रामिंग भाषाओं में, "अतिरिक्त" कोष्ठक का अर्थ है कि वे वाक्यविन्यास पार्सिंग क्रम या अर्थ को नहीं बदल रहे हैं । उन्हें कोड पढ़ने वाले लोगों के लाभ के लिए आदेश (ऑपरेटर पूर्वता) को स्पष्ट करने के लिए जोड़ा जा रहा है, और उनका एकमात्र प्रभाव संकलन प्रक्रिया को थोड़ा धीमा करना होगा, और कोड को समझने में मानवीय त्रुटियों को कम करना होगा (संभवतः समग्र विकास प्रक्रिया को गति देना। )।

यदि कोष्ठक का एक सेट वास्तव में एक अभिव्यक्ति को पार्स करने के तरीके को बदलता है, तो वे परिभाषा के अनुसार अतिरिक्त नहीं हैं । कोष्ठक जो एक अवैध / अवैध पार्स को कानूनी रूप से बदल देते हैं, वे "अतिरिक्त" नहीं हैं, हालांकि यह खराब भाषा डिज़ाइन को इंगित कर सकता है


2
ठीक है, और यह सी ++ में सामान्य नियम है (जैसा कि प्रश्न में मानक उद्धरण देखें), जैसा कि अन्यथा इंगित किया गया है । इन "कमजोरियों" को इंगित करना इस प्रश्नोत्तर का उद्देश्य था।
टेम्प्लेक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.