2011-10-05 16 views
9

मैं कोड का निम्न भाग, प्रकार है कि एक जटिल समारोह कॉल foo में मार डाला है पर वेतन वृद्धि ऑपरेटर के प्रभाव को उल्टा करने के प्रयास dec_proxy एक उदाहरण के रूप है - जो btw मैं नहीं कर सकता के इंटरफ़ेस को बदलें।सी में गैर स्थिरांक संदर्भ ++ के रूप में पासिंग temporaries

#include <iostream> 

template<typename T> 
class dec_proxy 
{ 
public: 
    dec_proxy(T& t) 
    :t_(t) 
    {} 

    dec_proxy<T>& operator++() 
    { 
     --t_; 
     return *this; 
    } 

private: 
    T& t_; 
}; 

template<typename T, typename S, typename R> 
void foo(T& t, S& s, R& r) 
{ 
    ++t; 
    ++s; 
    ++r; 
} 

int main() 
{ 
    int i = 0; 
    double j = 0; 
    short k = 0; 

    dec_proxy<int> dp1(i); 
    dec_proxy<double> dp2(j); 
    dec_proxy<short> dp3(k); 

    foo(dp1,dp2,dp3); 

    //foo(dec_proxy<int>(i),  <---- Gives an error 
    // dec_proxy<double>(j),  <---- Gives an error 
    // dec_proxy<short>(k));  <---- Gives an error 

    std::cout << "i=" << i << std::endl; 

    return 0; 
} 

समस्या यह है कि विभिन्न प्रकार के लिए मैं dec_proxy मैं वर्तमान में dec_proxy की एक विशेष उदाहरण बनाकर की आवश्यकता होती है का उपयोग करना चाहते है - यह एक बहुत ही गंदा और सीमित दृष्टिकोण की तरह लगता है।

मेरा प्रश्न है: गैर-कॉन्स संदर्भ पैरामीटर के रूप में ऐसे अल्पकालिक अस्थायी को पारित करने का सही तरीका क्या है?

+0

ऑब्जेक्ट को मूल्य से क्यों पास नहीं किया जाता है? –

+1

क्योंकि, यह है कि foo को कैसे परिभाषित किया गया है, मैं foo को नहीं बदल सकता और क्योंकि foo कई पैरामीटर लेता है। –

+1

उस मामले में, उत्कृष्ट सवाल। –

उत्तर

12

स्टीफन सलाह ले रहा है, तो आप How come a non-const reference cannot bind to a temporary object? का जवाब पर गौर करना चाहिए और केवल एक सदस्य समारोह है कि एक संदर्भ dec_proxy देता है, उदाहरण के लिए जोड़ें:

dec_proxy &ref() { return *this; }

और फोन foo:

foo(
    dec_proxy<int>(i).ref(), 
    dec_proxy<double>(j).ref(), 
    dec_proxy<short>(k).ref()); 

मुझे यकीन है कि संकलन है।

+0

अच्छा कामकाज :) – Geoffroy

2

आप जो करना चाहते हैं वह एक रैवल्यू (new dec_facade<int>(i)) को एक लवल्यू संदर्भ के रूप में पास करना है, जो बताता है कि यह क्यों काम नहीं करता है।

आप इसे समर्थन कंपाइलर हैं, तो आप, rvalue संदर्भ का उपयोग कर सकते हैं && प्रकार संशोधक का उपयोग करके: (rvalue संदर्भ के लिए समर्थन C++ 0x या सी ++ 11 [आंशिक] समर्थन पर स्विचन द्वारा सक्रिय किया जा सकता है)

template<typename T> 
void foo(T& t) 
{  
    ++t; 
} 
template<typename T> 
void foo(T&& t) 
{  
    ++t; 
} 

लेकिन समस्या का केवल एक हिस्सा है। आप क्या करने का प्रयास करते हैं, अस्थायी मूल्य को पूर्व-वृद्धि करना है! यह गैर-समझ में नहीं है, क्योंकि यह उस कॉल के बाद नहीं रहेगा। आपका ऑब्जेक्ट बढ़ जाएगा, फिर नष्ट हो जाएगा।


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

+0

वास्तव में के लिए सी ++ 11 एक अच्छा समाधान है यही कारण है, लेकिन मैं उम्मीद कर रही थी कि शायद वहाँ भी यह में क्या करना सी ++ 03 एट अल एक साफ रास्ता हो सकता है। –

+3

नहीं, यह ** ** बकवास नहीं है, फिर कोड को देखें। मुखौटा सिर्फ कॉल को प्रतिनिधि देता है, भले ही यह स्वयं एक अस्थायी है, प्रभाव खो जाएगा नहीं। वस्तु एक rvalue है –

+0

@KonradRudolph है, यह वृद्धि की जाएगी, लेकिन आप किसी भी परिणाम नहीं देख के रूप में यह कोई foo की गुंजाइश के अंत में नष्ट हो जाएगा होगा? – Geoffroy

7

एमएसएन, समाधान के लिए धन्यवाद:

मुझे नहीं लगता कि यह समारोह टेम्पलेट template<typename T> dec_proxy_impl<T>& dec_proxy(T&t) जोड़कर सही है।

यह क्या हुआ सिर्फ धोखा संकलक है। इसके परिणामस्वरूप रनटाइम त्रुटि होगी। फ़ंक्शन foo को lvaue या lvalue संदर्भ की आवश्यकता है। लेकिन template<typename T> dec_proxy_impl<T>& dec_proxy(T&t) एक मान्य lvalue संदर्भ वापस नहीं करता है। कार्यान्वयन में, यह एक अस्थायी वस्तु बनाता है, और इसे वापस करता है। फ़ंक्शन कॉल समाप्त होने के बाद, अस्थायी वस्तु नष्ट हो जाएगी। तो फ़ंक्शन foo फ़ंक्शन में पारित मान संदर्भ गलत है। दरअसल संदर्भित वस्तु पहले ही नष्ट हो चुकी है। ++t;++s;++r अमान्य वस्तुओं तक पहुंचने का प्रयास कर रहे हैं। व्यवहार अपरिभाषित है।

एमएसएन का समाधान सही है। ऑब्जेक्ट का जीवन समय dec_proxy<int>(i) फ़ंक्शन कॉल के अंत तक इसकी घोषणा से है। यह सुनिश्चित करता है कि फ़ंक्शन foo में पैरामीटर मान्य है।

+0

आप सही हैं। मुझे डर है कि इस प्रकार संकलक को धोखा देना भी संभव है। Temporaries एक अलग प्रकार है कि नहीं, किसी भी तरह से, एक गैर अस्थायी करने के लिए मजबूर किया जा सकता है (यह रूप में अच्छी तरह kaputt एमएसएन के समाधान प्रस्तुत करना होगा, लेकिन मुझे लगता है कि साथ रह सकता है, खासकर जब वहाँ rvalue संदर्भ हैं) होना चाहिए। –

+0

@ कोनराड रुडॉल्फ, अस्थायी पहले से ही मनमाने ढंग से कोड चला सकते हैं; मुद्दा (मैंने जो जवाब दिया है, उसमें भी उल्लेख किया गया है) यह है कि आप अस्थायी परिचालनों पर निहित परिचालन कर सकते हैं या नहीं। यदि आप स्पष्ट रूप से सदस्य कार्यों को कॉल करके अस्थायी रूप से छेड़छाड़ कर रहे हैं, तो यह ठीक है (क्योंकि यह स्पष्ट है)। – MSN

+0

@MSN मुझे पता है, लेकिन यह टाइप सिस्टम को घटा देता है। आदर्श रूप से, एक प्रकार की प्रणाली किसी भी अवैध संचालन को मना कर देगी। अब, यह साबित करना मुश्किल है कि इस प्रकार की एक प्रणाली को संकलन समय पर लागू नहीं किया जा सकता है (यह रोक समस्या को हल करेगा)। लेकिन मैं चाहता हूँ प्रकार प्रणाली संभव के रूप में सख्त होने के लिए और यह (कम से कम पहली नजर में) मुझे लगता है कि स्थानीय संदर्भ गुंजाइश रिसाव स्थिर सभी परिस्थितियों में जाँच की जा सकती है। –

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