2016-02-15 15 views
10

MSVC, जीसीसी और बजना के अनुसार, निम्नलिखित कोड अवैध है:सार्वभौमिक संदर्भ पैरामीटर के साथ एक समारोह टेम्पलेट में एक वर्ग टेम्पलेट का उपयोग करना

template <typename T> 
void f(T&& e) { 
    std::vector<T> v; 
    // do something with v and e ... 
} 
int main() { 

    int i; 
    f(i); 
} 

MSVC पैदावार

xmemory0 (591): त्रुटि सी 2528: 'पॉइंटर': संदर्भ में सूचक अवैध

जीसीसी और क्लैंग समान ध्वनि त्रुटि संदेश देते हैं। ध्यान दें कि सार्वभौमिक संदर्भ पैरामीटर e का उपयोग नहीं किया जाता है।

टिप्पणी: संकलक जाहिर वेक्टर v का दृष्टांत के लिए, के बारे में यह int के लिए एक संदर्भ के साथ इस्तेमाल किया जा रहा शिकायत में विफल रहता है कक्षा टेम्पलेट इन्स्टेन्शियशन के संदर्भ में देखना 'std::vector<T,std::allocator<_Ty>>'

[ 
     T=int &, 
     _Ty=int & 
    ] 

साथ संकलित किया जा रहा लेकिन मैं नहीं देख सकता कि फ़ंक्शन टेम्पलेट fint के संदर्भ के साथ तत्काल है।

क्या कोई यहां संकलक त्रुटियों की व्याख्या कर सकता है जो हम यहां देखते हैं?

+5

ध्यान दें कि * अग्रेषण संदर्भ * अब पसंदीदा शब्द है। – TartanLlama

उत्तर

18

f एक lvalue int के साथ बुलाया जाता है, Tint& के रूप में निष्कर्ष निकाला जाएगा, ताकि v एक std::vector<int&> हो जाएगा। यह अमान्य है ,

template <typename T> 
void f(T&& e) { 
    using value_type = typename std::remove_reference<T>::type; 
    //using value_type = std::remove_reference_t<T>; for C++14 
    std::vector<value_type> v; 
    // do something with v and e ... 
} 

लेकिन यदि आप समारोह संभव के रूप में सामान्य होना चाहते हैं, तो आप std::decay बजाय std::remove_reference उपयोग करना चाहिए:

एक तरीका यह चारों ओर पाने के लिए उपयोग करने से पहले T से संदर्भ हटाने के लिए है। यह f सीवी-योग्य प्रकार, सरणी और कार्यों के साथ काम करेगा।

+2

हालांकि 'C++ 11' टैग किया गया है, शायद यह भी 'remove_reference_t' का सुझाव है? यह इसे एक अच्छा लाइनर बनाता है। –

+0

@YamMarcovic धन्यवाद, मैंने इसे जोड़ा है, हालांकि मैं इसे एक से दो लाइनों पर करूँगा। – TartanLlama

+0

पाठकों के लिए एक नोट: मैं इस बात पर जोर देना चाहूंगा कि चूंकि एफ एक फ़ंक्शन टेम्पलेट है, यहां तक ​​कि टी में std :: vector टी टी बन जाता है जब एफ को lvalue के साथ तत्काल किया जाता है, उत्तर के नियमों के अनुसार। इससे पहले, मेरी समझ यह थी कि टी में std :: vector टी में टी से अलग नहीं हो सकता है। –

7

स्कॉट मेयर्स इस article में बताते हैं।

यदि सार्वभौमिक संदर्भ प्रारंभ करने वाली अभिव्यक्ति एक अंतराल है, तो सार्वभौमिक संदर्भ एक अंतराल संदर्भ बन जाता है।

यदि अभिव्यक्ति सार्वभौमिक संदर्भ प्रारंभ करना एक रैल्यू है, तो सार्वभौमिक संदर्भ एक रैल्यू संदर्भ बन जाता है।

अपने मामले i में एक lvalue है और इसलिए Tint& के रूप में निष्कर्ष निकाला गया है।

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