2011-09-09 16 views
5

क्या यह एक दोस्त के रूप में operator "" (...) को परिभाषित करने के लिए संभव और/या उपयोगी होगा?सी ++ 0x, उपयोगकर्ता ऑपरेटर के साथ उपयोगकर्ता परिभाषित अक्षर "" (0

class Puzzle { 
    friend Puzzle operator "" _puzzle(const char*, size_t); 
    ... 
}; 
void solve(Puzzle); 
int main() { 
    solve("oxo,xox"_puzzle); 
}; 

मैं नियम है कि operator "" एक नाम स्थान में ही परिभाषित किया जाएगा की वजह से, के बारे में "उपयोगी" विशेष रूप से सोच रहा हूँ - कम से कम नहीं है क्योंकि _ के साथ शुरुआत पहचानकर्ता ग्लोबल नेम स्पेस में आरक्षित हैं। क्या यह friend इस नियम को तोड़ रहा है? तो, इस तरह के पर्याप्त encapsulation के साथ कोई फायदा नहीं होगा, है ना?

उत्तर

2

स्टैंडर्ड पते इस सीधे ही जगह यह उपयोगकर्ता परिभाषित शाब्दिक की घोषणाओं पर कोई प्रतिबंध का उल्लेख है, §13.5.8/2 में:

एक जिसका declarator-आईडी घोषणा एक शाब्दिक-ऑपरेटर है -इड्स नामस्थान-स्कोप फ़ंक्शन या फ़ंक्शन टेम्पलेट की घोषणा होगी (यह एक मित्र फ़ंक्शन (11.3)) हो सकता है, एक स्पष्ट तत्काल या फ़ंक्शन टेम्पलेट का विशेषज्ञता, या उपयोग-घोषणा (7.3.3)।

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

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

यदि मित्र को क्लास टेम्पलेट के अंदर परिभाषित किया गया है, तो टेम्पलेट के दो इंस्टॉलेशनेशन नामस्थान स्कोप पर दो समान नामित फ़ंक्शंस उत्पन्न करेंगे, जो कि क्लास स्कोप के बाहर दोनों अदृश्य हैं, भले ही टकरा जाए।

class Integer; 
namespace literals { 
    Integer operator "" _I (const char *); 
} 

// Infinite precision integer 
class Integer { 
    public: 

    // Basic constructor & destructor 
    Integer(); 
    ~Integer(); 

... rest of the interface ... 

    // Literal operator 
    friend Integer literals::operator "" _I (const char *); 

    private: 

    struct Detail; 
    std::unique_ptr<Detail> detail; 

}; 

उपयोगकर्ताओं को एक साथ ऑपरेटर में खींच:

+0

मैंने वास्तव में सोचा कि मैंने इसे कहीं पढ़ा है, प्रत्यय * * केवल ** नामस्थान ** के अंदर घोषित किया जाना चाहिए। मुझे याद नहीं है - लेकिन यह केवल एक सुझाव था, आवश्यकता नहीं। और इसलिए, यह शायद "अच्छी प्रथा" के लिए एकमात्र युक्ति थी। ** टेम्पलेट ** मित्र समारोह के बारे में अच्छा बिंदु। यह सामान्य * मित्र * पैटर्न के साथ कोई मुद्दा नहीं है, मित्र समारोह में कम से कम एक तर्क क्या एक वर्ग उदाहरण है - तब कोई नामकरण समस्या नहीं है। – towi

+1

मुझे पहले की स्थिति के कागजात में ऐसा कुछ याद रखना याद है। N2378.pdf अनुभाग 5 का प्रयास करें: एक मुहावरे। यहां वे कहते हैं: 1. ये कार्य एडीएल के माध्यम से नहीं पाए जाते हैं जब स्पष्ट ऑपरेटर फॉर्म के बजाय अक्षर के माध्यम से बुलाया जाता है। 2. यह वैश्विक में नियुक्ति का लुत्फ उठाएगा। 3. इससे कोड में भी संघर्ष हो सकता है जो शाब्दिक उपयोग नहीं करता है। 4. तो शाब्दिक ओप को एक नामस्थान में रखें और उन्हें वैश्विक स्तर पर खींचने के लिए एक निर्देश का उपयोग करें। – emsr

+0

मैं सिर्फ यह ध्यान रखना चाहता था कि आप वर्ग के अंदर निजी रूप से मित्र समारोह का उपयोग नहीं कर सकते हैं, [यह सवाल] देखें (http://stackoverflow.com/questions/8207633/whats-the-scope-of-inline-friend -functions)। – Xeo

0

मानक के अनुसार, हाँ, एक मित्र घोषणा कानूनी होनी चाहिए। वैसे, नाम उपयोगकर्ता कोड के लिए ठीक है क्योंकि यह वैश्विक नामस्थान में भी अंडरस्कोर से शुरू होता है।

मित्र घोषणा ऑपरेटर को क्लास-निजी डेटा तक पहुंचने की अनुमति देगी।

मैं मित्र शाब्दिक ऑपरेटरों की उपयोगिता पर सवाल उठाना शुरू कर रहा हूं। चूंकि उपयोगकर्ता द्वारा परिभाषित ऑपरेटरों के पास केवल कुछ तर्क सूचियां हो सकती हैं, इसलिए कक्षाओं को तर्क में रखने का कोई तरीका नहीं है। तो सही कार्य खोजने के लिए तर्क निर्भर रूप से देखने के लिए अब रास्ता है। क्या मैं सही हू?

+0

मुझे लगता है कि एडीएल का उपयोग किया जा सकता है, लेकिन इसे 'कॉन्स्ट चार *' तर्क या जो भी आपके ऑपरेटर के लिए परिभाषित किया गया है उसे देखना है। लेकिन वैसे भी, मुझे उपयोगीता पर भी संदेह है: ठीक है, आप निजी डेटा तक पहुंच सकते हैं, लेकिन आपको किसी भी कन्स्ट्रक्टर को कॉल करने की आवश्यकता है। बीटीडब्ल्यू: जोहान्स (अन्य एन्वर टिप्पणियों) ने बताया कि नाम '_puzzle' नहीं है, लेकिन' ऑपरेटर "" _puzzle' है और इसलिए अंडरस्कोर से शुरू नहीं होगा। – towi

+0

हां, 13.5 के अनुसार।शाब्दिक ऑपरेटरों के लिए 8/7 नियमित लुकअप प्रबल होगा। मुझे नाम मुद्दा मिलता है। मैं 17.6.4.3.5 पर लटका हुआ था जो कार्यान्वयन के लिए एक प्रमुख अंडरस्कोर * बिना शाब्दिक प्रत्यय * रखता है। – emsr

+1

मुझे लगता है कि वे जिस मुख्य चीज के लिए डिजाइन किए गए थे, वह यह है कि वे लाइब्रेरी-केवल कार्यान्वयन की अनुमति दे सकते हैं, कहें, दशमलव। उपयोगकर्ता द्वारा परिभाषित शाब्दिक ऑपरेटरों लेक्सर में एक हुक प्रदान करते हैं। – emsr

1

मामले में यह वाक्य रचना के साथ मदद करता है, यहाँ कैसे मैं एक वर्ग है, जहां ऑपरेटर अपने आप में एक नाम स्थान में है में एक दोस्त उपयोगकर्ता परिभाषित शाब्दिक ऑपरेटर की घोषणा है using namespace literals; कथन केवल तभी जब वे चाहते हैं। (और, वास्तव में, यह सब एक मूल नामस्थान में है, लेकिन आपको विचार मिलता है)।

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