2011-08-09 12 views
36

safe bool idiom से निम्न अंश पर विचार करें:क्या ऐसे मामले हैं जहां टाइपिफ पूरी तरह जरूरी है?

typedef void (Testable::*bool_type)() const; 
operator bool_type() const; 

क्या टाइपपीफ के बिना रूपांतरण फ़ंक्शन घोषित करना संभव है? निम्नलिखित संकलित नहीं करता है:

operator (void (Testable::*)() const)() const; 
+3

तुम क्यों घोषणा करेंगे टाइपपीफ के बिना काम? –

+0

सुरक्षित बूल में रूपांतरण बिल्कुल जरूरी है? –

+0

@ टैड: यह मेरे विशेष मामले में उपयोगी लगता है (एक 'वैकल्पिक ' कक्षा टेम्पलेट)। – fredoverflow

उत्तर

9

आह, मैं सिर्फ याद identity मेटा-फ़ंक्शन। यह identity की निम्नलिखित परिभाषा के साथ

operator typename identity<void (Testable::*)() const>::type() const; 

लिखने के लिए संभव है:

template <typename T> 
struct identity 
{ 
    typedef T type; 
}; 

आप तर्क दे सकते हैं कि identity अभी भी एक typedef का उपयोग करता है, लेकिन इस समाधान "अच्छा" पर्याप्त मेरे लिए है।

+0

मैं इसका जवाब देने जा रहा था ... 'पहचान' पार्सिंग समस्याओं के आसपास होने का एक अच्छा तरीका है। –

+0

@ डेविड: अफसोस की बात है, 'पहचान' हिस्सा नहीं है मानक सी ++ 0x का। इस मामले में, हम 'std :: decay' का उपयोग कर सकते हैं, हालांकि ... – fredoverflow

+0

यह एक बेहतर संस्करण है जिसके लिए मैं जा रहा था! – AJG85

2

मेरे विश्लेषण कहना है कि यह typedef का उपयोग किए बिना संभव नहीं है। कंपाइलर पहले टोकन के रूप में ( देखता है और मानता है कि आप () operator ओवरलोड कर रहे हैं, जिसमें कोई तर्क नहीं होना चाहिए (तर्क ब्रांड्स के अगले सेट में आएंगे)। अतिरिक्त कोष्ठक का कोई भी सेट रखना या तो मदद नहीं करेगा - लेकिन वास्तव में संकलक को भ्रमित करेगा और इसलिए अधिक त्रुटियों का सेट करेगा।

अधिकांश एसटीएल कोड typedef संक्रमणों के शीर्ष पर है, और हमें उनका उपयोग करना चाहिए/

1

typedef मैक्रो नहीं है आपका दूसरा उदाहरण पहले के बराबर नहीं है। पहले मामले में आपका typedef फ़ैक्टर को परिभाषित कर रहा है, फिर उस प्रकार का उपयोग फ़ैक्टर प्रकार के कास्ट ऑपरेटर में कर रहा है। दूसरे में ऑपरेटर खराब वाक्यविन्यास का उपयोग कर रहा है क्योंकि कोई ऑपरेटर निर्दिष्ट नहीं है क्योंकि कोई प्रकार नहीं है। मुझे यकीन नहीं है कि इसे कैसे लिखना है लेकिन आमतौर पर एक तरीका है।

टीपीपी में मानव पठनीय कोड बनाने के अलावा टाइपपीफ वास्तव में आवश्यक नहीं हैं और फिर भी यह इस बात पर निर्भर करता है कि आप किस तरह के मानव हैं।

चूंकि मैं वैकल्पिक वाक्यविन्यास के साथ नहीं आ सकता क्योंकि शायद कुछ मामलों में टाइपपीफ आवश्यक हैं। मैंने बस एक और संभवतः सोचा।

template <typename T> 
struct WhateverHandler 
{ 
    typedef T rType; 
    static rType Whatever() { return rType(); } 
}; 

template <> 
struct WhateverHandler<std::string> 
{ 
    typedef std::string rType; 
    static rType Whatever() { return rType(); } 
}; 

मैं इस मामले में लगता है कि यह भी आप अन्यथा के रूप में विशेषज्ञता की परवाह किए बिना स्थिर विधि कॉल करने में typedef की आवश्यकता होगी: आप जो नीचे की तरह एक वापसी प्रकार के साथ एक स्थिर विधि निहित विशेषज्ञता के साथ एक टेम्पलेट था कहो विधि संकलक को भ्रमित कर सकती है क्योंकि रिटर्न प्रकार अलग-अलग होंगे लेकिन यह उचित अधिभार नहीं होगा।

template <typename T> 
struct WhateverUser 
{ 
    typename WhateverHandler<T>::rType DoWhatever() 
    { 
     return WhateverHandler<T>::template Whatever(); 
    } 
}; 
3

ही एक मामला (अपने प्रश्न से संबंधित नहीं) जहां एक typedef की आवश्यकता है जब

va_arg() मैक्रो का उपयोग है। C99 मानक (7.15.1.1) का हवाला देते हुए:

प्रकार * va_arg (va_list एपी, प्रकार);

...

पैरामीटर प्रकार एक प्रकार निर्दिष्ट नहीं है कि इस तरह का नाम होगा एक वस्तु के लिए सूचक के प्रकार है कि निर्दिष्ट प्रकार एक postfixing द्वारा बस प्राप्त किया जा सकता है * प्रकार

+1

वहाँ एक और ऐसा मामला है, अर्थात् छद्म-विनाशक –

+0

आईई 'पी-> ~ हस्ताक्षरित चार() 'की अनुमति नहीं है (उन लोगों के लिए जो नहीं जानते कि छद्म-विनाशक क्या है या आपको इसकी आवश्यकता क्यों है वहाँ एक टाइपिफ़)। – MSalters

3

उत्तर देना "वहाँ मामलों में जहां एक typedef बिल्कुल जरूरी है कर रहे हैं के लिए?

f(unsigned char()); // compiler error! 
typedef unsigned char Byte; 
f(Byte());   // fine! 

यहाँ परिणाम देखें:: "सवाल शीर्षक से, यहाँ है, जहां एक typedef की जरूरत है की एक उदाहरण है। http://ideone.com/JPUra

+0

कंपाइलर युद्ध फिर से! जीसीसी विफल रहता है, वीसी सफल होता है। – Ajay

+1

'एफ (पहचान <हस्ताक्षरित चार> :: प्रकार())'?;) – fredoverflow

+2

@FredOverflow ऐसा लगता है कि यह काम करेगा, हालांकि तकनीकी रूप से 'टाइप' एक टाइपपीफ है। : पी –

2

ऐसा लगता है कि व्याकरण आपके मामले में एक typedef का उपयोग कर की मांग एक रूपांतरण समारोह-आईडी इस रूप में होने चाहिए ऑपरेटररूपांतरण प्रकार आईडीरूपांतरण प्रकार आईडी कोष्ठकों नहीं हो सकते। तो तुम जब एक सूचक करने वाली समारोह प्रकार में कनवर्ट करने typedef का उपयोग करना चाहिए, या एक पॉइंटर-टू-सदस्य-फ़ंक्शन प्रकार के लिए ।

+0

"रूपांतरण-प्रकार-आईडी में कोष्ठक नहीं हो सकते हैं।" आप इसे कहां से प्राप्त करते हैं? – TonyK

+0

@ टोनीके: व्याकरण से। यह मूल रूप से शायद एक कॉन्स/अस्थिर आदिम प्रकार या एक योग्य आईडी (प्रकार-विनिर्देशक-सीईसी) है, इसके बाद शून्य या अधिक सूचक-ऑपरेटर (रूपांतरण-घोषणाकर्ता-ऑप्ट)। –

+0

@ एन: मुझे एक रास्ता मिला: 'टेम्पलेट कक्षा सी {}; कक्षा एस {ऑपरेटर सी <(99)> *() {वापसी 0; }}; ' – TonyK

2

सी ++ 11 में, आप इसे इस (जीसीसी 4.5.2) की तरह कर सकते हैं:

operator decltype((void (Testable::*)() const)(0))() const ; 

मैं यह नहीं कह रहा हूँ कि यह बहुत है ...

+0

रुको, मैंने अभी इसे वीसी 10 में आजमाया है और यह काम नहीं करता है :(C2833 – fredoverflow

+0

क्या आपने' decltype (& testable :: foo) 'के साथ प्रयास किया है, जहां 'foo' उपयुक्त हस्ताक्षर के साथ सदस्य विधि है? –

+0

@ डेविड: यूप, या तो काम नहीं करता है :(सी 2833 फिर से – fredoverflow

1

मैं सिर्फ इस मुद्दे भर में भाग गया, बजना साथ ++:

foo.cpp:17:8: error: must use a typedef to declare a conversion to 'void (*(int))()' 

और वहाँ एक सी ++ 11 एसटीएल टेम्पलेट जो पहचान < टी > कार्यक्षमता को शामिल किया गया है:

#include <type_traits> 
… 
struct foo { 
    void bar() const { } 
    operator std::common_type<void(foo::*)()const>::type() { return &foo::bar; } 
}; 
संबंधित मुद्दे

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