2016-04-01 12 views
8

यह ++उपयोगकर्ता-परिभाषित इन्फ़िक्स ऑपरेटरों

// User-defined infix operator framework 

template <typename LeftOperand, typename Operation> 
struct LeftHelper 
{ 
    const LeftOperand& leftOperand; 
    const Operation& operation; 
    LeftHelper(const LeftOperand& leftOperand, 
       const Operation& operation) 
     : leftOperand(leftOperand), operation(operation) {} 
}; 

template <typename LeftOperand, typename Operation > 
auto operator < (const LeftOperand& leftOperand, 
       Operation& operation) 
{ 
    return LeftHelper<LeftOperand, Operation>(leftOperand, operation); 
} 

template <typename LeftOperand, typename Operation, typename RightOperand> 
auto operator > (LeftHelper<LeftOperand, Operation> leftHelper, 
       const RightOperand& rightOperand) 
{ 
    return leftHelper.operation(leftHelper.leftOperand, rightOperand); 
} 

// Defining a new operator 

#include <cmath> 
static auto pwr = [](const auto& operand1, const auto& operand2) { return std::pow(operand1, operand2); }; 

// using it 
#include <iostream> 
int main() 
{ 
    std::cout << (2 <pwr> 16) << std::endl; 
    return 0; 
} 

Live demo

दुर्भाग्य से, यह शक्ति ऑपरेटर गलत पूर्वता और संबद्धता है सी में नई इन्फ़िक्स ऑपरेटरों को लागू करना आसान है। तो मेरा सवाल है: इसे कैसे ठीक करें? मैं <pow> चाहता हूं कि * से अधिक प्राथमिकता हो और गणितीय नोटेशन की तरह, दाईं ओर संबद्ध हो।

संपादित करें विभिन्न ब्रैकेट्स का उपयोग करके प्राथमिकता को बदलना संभव है, उदा। |op|, /op/, *op* या यहां तक ​​कि यदि कोई ऐसा इच्छुक है, <<--op-->>, लेकिन कोई भी इस तरह से उच्चतम अंतर्निहित ऑपरेटर प्राथमिकता से अधिक नहीं जा सकता है। लेकिन आज सी ++ टेम्पलेट मेटाप्रोग्रामिंग के साथ इतना शक्तिशाली है और कटौती टाइप करें, वांछित परिणाम प्राप्त करने के लिए बस कुछ और तरीका होना चाहिए।

इसके अतिरिक्त, यह अच्छा होगा अगर मैं pow का उपयोग कर सकता हूं और pwr नहीं। दुर्भाग्यवश कुछ कार्यान्वयन में #include <cmath> वैश्विक नामस्थान में pow लाता है, इसलिए एक संघर्ष होगा। हम ओवरलोड कर सकते हैं operator not ऐसी है कि प्रपत्र

not using std::pow; 

की घोषणा हटा दिया ग्लोबल नेम स्पेस से std::pow?

आगे पढ़ने: a related proposal by Bjarne Stroustrup

+6

"आसान" .......... हे हा। (जैसे, गंभीरता से, मुझे आशा है कि यह केवल अनुसंधान उद्देश्यों के लिए है) –

+7

आप * नए ऑपरेटरों को "आविष्कार" नहीं कर सकते हैं, आप बस ऑपरेटर के समान काम करने वाले कुछ अनुकरण करने के लिए मौजूदा ऑपरेटरों का उपयोग करते हैं लेकिन वास्तविक ऑपरेटर नहीं हैं। यही कारण है कि ऑपरेटर प्राथमिकता काम नहीं कर रही है। और अपने प्रश्न का उत्तर देने के लिए, इसे ठीक करने का कोई तरीका नहीं है। –

+2

यह "रन टू" ऑपरेटर के लिए थोड़ा सा विचार है: 'जबकि (i ----> 0) '। बेहद सुविधाजनक! – user2079303

उत्तर

6

कम से कम आश्चर्य का सिद्धांत महत्वपूर्ण है, और यह महत्वपूर्ण है कि a*b *power* c * da* (b^c) *d का मूल्यांकन करें। सौभाग्य से एक आसान समाधान है।

यह सुनिश्चित करने के लिए कि *power* गुणा की तुलना में अधिक प्राथमिकता है, आपको गुणा के लिए एक समान नामांकित ऑपरेटर तकनीक का उपयोग करना होगा।

फिर *power* और *times* के परिणामों की सीधे गणना करने की बजाय, आप इसके बजाय एक अभिव्यक्ति वृक्ष बनाते हैं। मूल्यांकन के पेड़, जब मूल्यांकन किया गया, मनमाने ढंग से प्राथमिकता नियम लागू कर सकते हैं।

हम साथ ऐसा कर सकते हर निर्मित ऑपरेटर, हमें वाक्य रचना संकलन समय की अनुमति देता है पढ़ने के लिए ऑपरेटर पूर्वता metaprogramming एक आसान दे रही है:

auto z =equals= bracket< 
    a *plus* b *times* c *power* bracket< 
    a *plus* b 
    >bracket *power* x *times* y 
>bracket; 

इष्टतम से अधिक समय संग्रहीत किए जाने से इस अभिव्यक्ति टेम्पलेट से बचने के लिए , प्रयुक्त प्रकार को वापस करने के लिए बस operator auto()&& अधिभारित करें। यदि आपका कंपाइलर उस सुविधा का समर्थन करने में विफल रहता है, तो =equals= उचित प्रकार की स्पष्टता पर उचित प्रकार को वापस कर सकता है।

ध्यान दें कि उपर्युक्त वाक्यविन्यास वास्तव में ओपी के समान तकनीकों का उपयोग करके सी ++ में प्राप्य है। एक एसओ पोस्ट में एक वास्तविक कार्यान्वयन बड़ा होना चाहिए।

अन्य लाभ भी हैं।हर कोई जानता है के रूप में, प्रोग्रामिंग भाषाओं में अस्पष्ट ASCII वर्ण पक्ष से बाहर गिर गए हैं, और सी ++ पढ़ने लोगों की तरह भाव से confuesed जा सकता है:

int z = (a + b* pow(c,pow(x,a+b))*y); 
इस तकनीक के साथ

, सभी ऑपरेटरों पठनीय ऐसे नाम हैं जो उनके अर्थ स्पष्ट करना है, और इन्फिक्स और उपसर्ग नोटेशन को मिश्रित करने के बजाय सब कुछ इंफिक्स किया जाता है।

pow यह सुनिश्चित करने के लिए इसी तरह के समाधानको <cmath_nopow> के रूप में पुनः कार्यान्वित करके किया जा सकता है। यह ऑपरेटर ओवरलोडिंग ऑपरेटर से नहीं है भाषा संरचनाओं पर, जो एएसटी व्याकरण को decouple करने के लिए monads, और/या मानक का उल्लंघन करता है। शायद हास्केल आज़माएं?

+1

यह एक अच्छा विचार है। यदि कोई शीर्ष स्तर पर ब्रैकेटिंग के लिए हमेशा 'ब्रैकेट/.../ब्रैकेट' का उपयोग करता है, तो गुणा के लिए मानक '*' नोटेशन को बनाए रखना भी संभव होना चाहिए! हास्केल के लिए ... मुझे पता नहीं, शायद स्नोयमैन [किसी भी मोनाद को ठीक करें] (http://www.yesodweb.com/blog/2016/04/fixing-monad-either)? –

+1

@ एनएम। मुझे नहीं पता, 'ब्रैकेट /' भ्रमित लग रहा है। हम 'ब्रा <' and '> केट 'का उपयोग कर सकते हैं, जो क्वांटम यांत्रिकी में पूर्व उपयोग फिट बैठता है। – Yakk

+0

यदि विरासत एक-प्रतीक ऑपरेटरों का उपयोग '*' जैसा है, तो आपको उच्चतम संभावित प्राथमिकता वाले ब्रैकेट की आवश्यकता है, इसलिए 'ब्रा < > केट', जो आकर्षक हैं, काम नहीं करेंगे। एक 'ब्रा// केट' जोड़ी शायद अगली सबसे अच्छी बात है। –

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