2012-02-17 17 views
6

मेरे पास है:decltype (समारोह) वर्ग के सदस्य के रूप में

int foo(int x) { return x+1; } 

struct Bar { 
    decltype(foo) operator(); 
}; 

int main() { 
    Bar bar; 
    printf("%d\n",bar(6)); 
} 

जो थोड़ा चौंकाने संकलक त्रुटि संदेश में परिणाम (छ ++ 4.6.1):

error: declaration of 'operator()' as non-function 

जब

के सदस्य का नाम भी बदलकर
decltype(foo) blubb; 

और यह एक लिंकर त्रुटि में परिणाम का उपयोग कर:

undefined reference to `Bar::blubb(int)' 

क्या यह अपेक्षित व्यवहार है?

+0

क्या आप वास्तव में फ़ंक्शन का प्रकार चाहते हैं, या इसके बजाय फ़ंक्शंस रिटर्न टाइप (जिसे आप "अस्वीकरण" जैसे "decltype (foo (0)) से कॉल कर सकते हैं) –

+0

मैं कहूंगा कि जीसीसी अभी तक अभी तक नहीं है इसे लागू किया यह क्लैंग में ठीक काम करता है। – PlasmaHH

+0

@phresnel: यह देखकर कि वह इसे कैसे आमंत्रित करता है ('बार (6)') मुझे लगता है कि वह समारोह चाहता है। हालांकि मुझे आश्चर्य है कि लिंकर त्रुटि एक शिकायत है (फ़ंक्शन को परिभाषित नहीं होने पर इसकी अपेक्षा की जाती है), या सिर्फ यह दिखाने के लिए कि यह फ़ंक्शन को ठीक बनाता है। – PlasmaHH

उत्तर

5

ऐसा लगता है कि आप एक ही हस्ताक्षर के साथ एक समारोह बनाने के लिए किसी अन्य फ़ंक्शन के हस्ताक्षर को "कॉपी" करना चाहते हैं। चूंकि decltype(foo) वास्तव में फ़ंक्शन का प्रकार है (और उस फ़ंक्शन के लिए पॉइंटर नहीं है, जो decltype(&foo) होगा और एक सूचक घोषणा के लिए नेतृत्व करेगा), आप इसे किसी अन्य फ़ंक्शन के समान हस्ताक्षर के साथ फ़ंक्शन घोषित करने के लिए उपयोग कर सकते हैं।

लिंकर त्रुटि ने संकेत के रूप में:

undefined reference to `Bar::blubb(int)' 

यह पहले से ही अपने संकलक के साथ ठीक से काम करेगा। हालांकि ऐसा लगता है कि जीसीसी ने अभी तक मानक के इस हिस्से को पूरी तरह कार्यान्वित नहीं किया है, क्योंकि यह फ़ंक्शन कॉल ऑपरेटर के साथ एक ही चीज़ के सिंटैक्स को स्वीकार नहीं करेगा। क्लैंग बीटीडब्ल्यू खुशी से यह और लिंक तो

undefined reference to `Bar::operator()(int)' 

क्यों कि लिंकर त्रुटि मौजूद है के बारे में आपका प्रश्न के साथ बाहर स्वीकार करेंगे त्रुटियों क्या decltype वास्तव में करता है की एक गलतफहमी इंगित करता है।

यह सिर्फ एक प्रकार का मूल्यांकन करेगा, और अधिक नहीं। blubb की परिभाषा foo की परिभाषा से बंधी नहीं है। यह स्पष्ट है जब यह की तरह

typedef decltype(foo) x; 
x blubb; 

लेखन हो सकता है अब आप वैकल्पिक रूप से typedef एक्स स्पष्ट रूप से समारोह का प्रकार, हो सकता है जो किसी भी तरह से परिवर्तन blubb है क्या में नहीं होगा। आपको अभी भी इसे परिभाषित करने की आवश्यकता है।और के बाद से वहाँ decltype का उपयोग कर इसे परिभाषित करने की कोई वाक्य रचना है, तो आप स्पष्ट रूप से के रूप में

int Bar::operator()(int) { 
... 
} 

यह लिखने के लिए जो संभावना और दुर्भाग्य से, घोषणा के लिए decltype का उपयोग करने का उद्देश्य/लाभ को हराने होगा के रूप में यह आप के लिए अनुमति नहीं दी जाएगी राशि हस्ताक्षर स्वचालित रूप से "प्रतिलिपि बनाएँ"।

2

यह एक जंगली यहाँ printf के आपके उपयोग को देख के आधार पर अनुमान है:

printf("%d\n",bar(6)); 

यह मैं मान की सुविधा देता है आप वास्तव में समारोह, नहीं समारोह के प्रकार के वापसी प्रकार चाहते हैं। यदि ऐसा है, तो आप decltype गलत का उपयोग करें। आप "अनुकरण" समारोह का उपयोग, द्वारा समारोह की वापसी प्रकार मिलता है अर्थात

decltype(foo(0)) operator() (int); 

आप के लिए सही काम किया जाना चाहिए। अन्यथा, यदि वह आपका ध्यान नहीं था, तो आप %d विनिर्देशक को फ़ंक्शन प्रकार (और फ़ंक्शन रिटर्न प्रकार नहीं) देकर पतली बर्फ पर स्केटिंग कर रहे हैं।

आम तौर पर, decltype का अर्थ है: decltype(@) अभिव्यक्ति का स्थिर प्रकार @ देता है।

+3

उस विचार को देखते हुए, आपके समाधान को भी होना चाहिए (यह भी चुनना होगा उपयोग पैटर्न ऊपर): 'decltype (foo (0)) ऑपरेटर() (int);' – PlasmaHH

+0

@PlasmaHH: ठीक है, धन्यवाद। –

+0

मैं 'सामान्य' पैटर्न के बारे में अच्छी तरह से जानता हूं। मेरा मतलब यह नहीं था, ऊपर मेरी पहली टिप्पणी देखें। फिर भी, आपका जवाब संभवत: अधिकांश उपयोगकर्ता वास्तव में चाहते हैं। – smilingthax

0

यह काम करना चाहिए। मैं सिर्फ यह यहां इस्तेमाल किया कब्जा करने के लिए जो कुछ भी गॉबल्डीगुक std::bind मुझे देने के लिए जा रहा था:

class RiceFadingModel::Impl 
{ 
public: 
    Impl(double K, double A) 
    : //... 
    _M_re{system_now()}, 
    _M_rd{_M_nu, _M_sigma}, 
    _M_gen{std::bind(_M_rd, _M_re)} 
    { } 


private: 

//... 

    std::default_random_engine _M_re; 
    /// The underlying Rice distribution. 
    __gnu_cxx::__rice_distribution<double> _M_rd; 
    /// The variate generator built from the pseudo-random number engine and the Rice distribution. 
    decltype(std::bind(_M_rd, _M_re)) _M_gen; 
}; 

यह जीसीसी-4.7 पर एक आकर्षण की तरह काम करता है। अब जब मैं इसके बारे में सोचता हूं तो मैंने इसे जीसीसी-4.5 के साथ भी मिंगव पर बनाया है।

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