2012-12-13 8 views
7

अद्यतन: मैं नीचे मेरे अपने उत्तर पोस्ट और वहाँ यहाँ इस मामले की एक लंबी संस्करण है: http://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-literalsसंकलन समय जैसे रूपांतरण की जांच (constexpr और उपयोगकर्ता परिभाषित शाब्दिक)

प्रश्न:

मैं हमने एक सरल constexpr उपयोगकर्ता को शाब्दिक _X परिभाषित किया है जो मान को एक लंबे समय तक हस्ताक्षरित के रूप में प्राप्त करता है (इस प्रकार संख्यात्मक उपयोगकर्ता परिभाषित अक्षर: http://en.cppreference.com/w/cpp/language/user_literal), और फिर मैं सुनिश्चित करता हूं कि मान लंबे समय तक हस्ताक्षरित हो।

यह सब अच्छी तरह से काम करता है (बहुत बड़ा मान संकलन त्रुटि के कारण), लेकिन केवल जब मैं स्पष्ट रूप से एक चर बनाने जैसे

constexpr auto a= 150_X; 

, तो इसके बजाय मैं कुछ विशिष्ट प्रकार लिख

cout << 150_X << endl;; 

परीक्षण संकलन समय पर प्रदर्शन नहीं किया जाता है।

  • constexpr कार्यों केवल संकलन समय पर क्रियान्वित कर रहे हैं अगर वे एक constexpr चर के लिए आवंटित कर रहे हैं? (मुझे मानक में यह नहीं मिला)

  • क्या _X का सुरक्षित व्यवहार प्राप्त करना संभव है जो मैं ढूंढ रहा हूं?

पूर्ण उदाहरण:

#include<iostream> 
#include<stdexcept> 

inline constexpr long long testConv(unsigned long long v) { 
    return (v > 100) ? throw std::exception() : v; 
} // will eventually use actual limit from numeric_limits 

inline constexpr long long operator "" _X(unsigned long long f) { 
    return testConv(f) ; 
} 

int main(){ 
    constexpr auto a= 5_X; 
    std::cout << a << std::endl; 
    std::cout << 200_X << std::endl; // This bad literal is accepted at compile time 
    constexpr auto c=250_X;   // This bad literal is not accepted at compile time 
    std::cout << c << std::endl; 
} 

ओह, संदर्भ के लिए: मैं gcc4.7.2 इस्तेमाल किया।

उत्तर

4

स्व जवाब: मैं एक पूर्ण समाधान, टिप्पणियों और मेरे सवाल का अन्य उत्तर, और इस तरह के रूप में https://stackoverflow.com/a/13384317/1149664 अन्य प्रश्न से प्रेरित पाया।

समाधान द्वारा 10

मैं यहाँ इस आत्म जवाब का एक विस्तृत संस्करण लिखा उपयोगकर्ता परिभाषित शाब्दिक की टेम्पलेट फार्म का उपयोग करें और मैन्युअल रूप से नंबर योग, पहले से ही पार्स अंकों के आधार पर राशि गुणा करने के लिए है : http://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-literals

template<char... Chars> 
int operator"" _steps(){ 
    return {litparser<0,Chars...>::value}; 
} 

Litparser एक छोटे से टेम्पलेट मेटा-प्रोग्राम है जो वर्ण पैरामीटर पैक द्वारा आयोजित इनपुट पात्रों से विस्तार तर्कों के रूप वर्णों की एक सूची लेता है।

typedef unsigned long long ULL; 

// Delcare the litparser 
template<ULL Sum, char... Chars> struct litparser; 

// Specialize on the case where there's at least one character left: 
template<ULL Sum, char Head, char... Rest> 
struct litparser<Sum, Head, Rest...> { 
// parse a digit. recurse with new sum and ramaining digits 
    static const ULL value = litparser< 
    (Head <'0' || Head >'9') ? throw std::exception() : 
    Sum*10 + Head-'0' , Rest...>::value; 
}; 

// When 'Rest' finally is empty, we reach this terminating case 
template<ULL Sum> struct litparser<Sum> { 
    static const ULL value = Sum; 
}; 
+0

ग्रेट उत्तर, और विस्तारित लेखन के लिए भी धन्यवाद! बहुत उपयोगी। – U007D

+0

यह, ज़ाहिर है, केवल तब तक काम करता है जब तक शाब्दिक कभी अष्ट या हेक्साडेसिमल नहीं होता है। इन मामलों में, विभिन्न शाब्दिक पार्सर की आवश्यकता होगी। – nshct

3

constexpr फ़ंक्शंस संकलित समय पर निष्पादित किया जा सकता है; अर्थात, वे निरंतर अभिव्यक्तियों में उपयोग किए जाने के लिए योग्य हैं। यदि उनका निरंतर अभिव्यक्ति में उपयोग नहीं किया जाता है, तो संकलन समय पर उन्हें निष्पादित करने का कोई मतलब नहीं है, हालांकि मुझे लगता है कि इसकी अनुमति है।

चूंकि आपको constexpr (सेक्शन 7.1.5/1) [1] के रूप में पैरामीटर घोषित करने की अनुमति नहीं है, इसलिए मुझे नहीं लगता कि संकलन समय पर operator "" _X(unsigned long long) के मूल्यांकन को मजबूर करने का कोई तरीका है, लेकिन आप शायद template<char...> operator "" _X()

यदि constexpr फ़ंक्शन निरंतर अभिव्यक्ति के भीतर बुलाया जाता है, तो तर्क निरंतर अभिव्यक्ति होगी (और यदि यह नहीं है, तो कॉल निरंतर अभिव्यक्ति नहीं है)। हालांकि, आप बलपैरामीटर को constexpr होने के लिए निरंतर अभिव्यक्ति होने के लिए कॉल नहीं कर सकते हैं, क्योंकि आपको constexpr के रूप में पैरामीटर घोषित करने की अनुमति नहीं है, मानक के संदर्भ देखें।


[नोट 1]: धन्यवाद मानक खोज पैरा दो में दावा का औचित्य साबित करने के लिए @LightnessRacesInOrbit करने के लिए।

+0

'चूंकि आपको कॉन्फ़ेक्सर हम्म के रूप में पैरामीटर घोषित करने की अनुमति नहीं है, वास्तव में? –

+1

हम्म हां वास्तव में (7.1.5/1) - लेकिन 'कॉन्स्टेक्सआर' आवश्यकता को "विरासत" कहा जाता है जिसे इसे निरंतर अभिव्यक्ति –

+0

@ लाइटनेसरेसेसिन ऑर्बिट के हिस्से के रूप में कहा जाता है: यह केवल "विरासत में है" फ़ंक्शन को निरंतर अभिव्यक्ति के हिस्से के रूप में जाना जाता है। आप एक स्थिरता अभिव्यक्ति का हिस्सा होने के लिए आग्रह करने के लिए 'constexpr' पैरामीटर के साथ फ़ंक्शन नहीं लिख सकते हैं। क्या यह स्पष्ट नहीं था? – rici

1

कॉन्सटेक्स कार्यों को संकलित समय पर निष्पादित करने की आवश्यकता नहीं है। लेकिन आपका लक्ष्य हासिल किया जा सकता है। समस्या की बेहतर समझ के लिए, और एक उदाहरण बनाने के लिए जो कि संकलन-समय पर हमेशा मूल्यांकन किया जाता है, मैं this post की सलाह देता हूं।

+0

धन्यवाद, जब आपने यह लिखा था तो मैंने पहले ही अपना जवाब पोस्ट कर दिया था। टेम्पलेट्स और मैन्युअल पार्सिंग रास्ता है ... आपके लिए अच्छा ब्लॉग +1 (जिसे मैं पहले से ही अनुवर्ती करता हूं)। –

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