2015-02-18 8 views
6

नीचे कोड पर विचार करें:अंतर्निहित रूपांतरण shared_ptr को

#include <iostream> 
#include <memory> 

void f(std::shared_ptr<int> sp) {} 

template <typename FuncType, typename PtrType> 
auto call_f(FuncType f, PtrType p) -> decltype(f(p)) 
{ 
    return f(p); 
} 

int main() 
{ 
    f(0); // doesn't work for any other int != 0, thanks @Rupesh 
    // call_f(f, 0); // error, cannot convert int to shared_ptr 
} 

पहली पंक्ति में main() में, पूर्णांक 0 एक std::shared_ptr<int> में बदल जाती है और कॉल f(0) किसी भी समस्या के बिना सफल होता है। हालांकि, फ़ंक्शन को कॉल करने के लिए टेम्पलेट का उपयोग करके चीज़ें अलग-अलग होती हैं। दूसरी पंक्ति अब और संकलन नहीं होगा, त्रुटि जा रहा है

error: could not convert 'p' from 'int' to 'std::shared_ptr<int>' 

मेरे सवालों का कर रहे हैं:

  1. क्यों पहली कॉल सफल होने करता है और दूसरा नहीं करता है? क्या मैं यहां कुछ भी याद कर रहा हूं?
  2. मुझे यह समझ में नहीं आता कि int से std::shared_ptr पर रूपांतरण f(0) पर किया जा रहा है, क्योंकि यह std::shared_ptr जैसा दिखता है केवल स्पष्ट निर्माता हैं।

पुनश्च: इस उदाहरण का एक प्रकार nullptr साथ इस तरह के कॉल की रक्षा करने के एक तरीके के रूप में, स्कॉट Meyers 'प्रभावी आधुनिक सी ++ आइटम 8 में दिखाई देता है।

+0

@@ vsoftco आप का उल्लेख करना चाहिए कि यह केवल 'च (0)', के अलावा कुछ भी नहीं है शून्य से संकलन है, अन्य के लिए एक ही त्रुटि के लिए काम कर रहा है:

मजेदार बात यह है कि यहां तक ​​कि इस कोड काम करता है, है पहले कॉल में मूल्य भी। –

+0

[यह] (http://en.cppreference.com/w/cpp/language/nullptr) एक स्पष्टीकरण पर संकेत देता है - "किसी भी सूचक प्रकार के नलप्टर से शून्य सूचक मूल्य और सदस्य प्रकार के किसी भी सूचक से निहित रूपांतरण मौजूद हैं। इसी तरह के रूपांतरण किसी भी प्रकार के std :: nullptr_t के साथ-साथ मैक्रो न्यूल, शून्य सूचक स्थिर के लिए मौजूद हैं। " लेकिन यह देखना दिलचस्प होगा कि यह मानक संदर्भों और अधिक स्पष्टता के साथ समझाया गया है। – Pradhan

+1

@RupeshYadav। किया हुआ। दरअसल, यह बहुत अजीब है, ऐसा लगता है कि किसी प्रकार का निहित सूचक रूपांतरण किया जा रहा है। – vsoftco

उत्तर

5

std::shared_ptr एक निर्माता कि std :: nullptr_t, लेता शाब्दिक 0 एक अशक्त सूचक लगातार कि एसटीडी करने के लिए convertiable है :: मानक खंड मसौदा C++ से nullptr_t है 4.10[conv.ptr] (जोर मेरा आगे जाने):

एक नल पॉइंटर लगातार एक अभिन्न निरंतर अभिव्यक्ति (5.19) है कि शून्य या प्रकार +०१२३५१६४१०६१ के prvalue का मूल्यांकन पूर्णांक प्रकार की prvalue हैstd :: nullptr_t।एक शून्य सूचक स्थिर को सूचक प्रकार में परिवर्तित किया जा सकता है; नतीजा उस प्रकार का शून्य सूचक मूल्य है और ऑब्जेक्ट पॉइंटर या फ़ंक्शन सूचक प्रकार के प्रत्येक अन्य मान से अलग है। इस तरह के एक रूपांतरण को शून्य सूचक रूपांतरण कहा जाता है। उसी प्रकार के दो शून्य सूचक मान बराबर की तुलना करेंगे। सीवी-योग्य प्रकार के लिए एक पॉइंटर को निरंतर शून्य सूचकांक का रूपांतरण एक एकल रूपांतरण है, और एक सूचकता रूपांतरण के अनुक्रम के बाद योग्यता रूपांतरण (4.4) के अनुक्रम का अनुक्रम नहीं है। एक शून्य अभिन्न प्रकार के सूचक स्थिरांक को प्रकार के std :: nullptr_t के रूप में परिवर्तित किया जा सकता है। [नोट: परिणामी प्रसार एक शून्य सूचक मूल्य नहीं है। अंत टिप्पणी]

अपने दूसरे मामले p में

पूर्णांक जो मान शून्य है, हालांकि अब एक नल पॉइंटर स्थिर है प्रकार के रूप में निष्कर्ष निकाला जा रहा है और इतने ही मामले से मेल नहीं खाती।

टीसी के रूप में। बताते हैं शब्दों DR 903 जिसका मान एक पूर्णांक शून्य के रूप में एक अभिन्न निरंतर अभिव्यक्ति जो शून्य करने के लिए मूल्यांकन करता है करने के लिए विरोध के साथ शाब्दिक की आवश्यकता के साथ बदल गया था:

एक नल पॉइंटर लगातार एक पूर्णांक शाब्दिक (2.14.2) है मूल्य शून्य या टाइप std :: nullptr_t के प्रकार के साथ। एक शून्य सूचक स्थिर को एक सूचक प्रकार में परिवर्तित किया जा सकता है; नतीजा शून्य सूचक उस प्रकार का मान है और ऑब्जेक्ट पॉइंटर या फ़ंक्शन पॉइंटर प्रकार के हर दूसरे मान से अलग है।

+0

अधिक अद्यतन ड्राफ्ट का उपयोग करना चाहते हैं (नीचे @ केसी का जवाब देखें)। आईआईआरसी "इंटीग्रल निरंतर अभिव्यक्ति (5.1 9) पूर्णांक प्रकार का अभिकर्मक जो शून्य का मूल्यांकन करता है" इसमें ऐसे रत्न शामिल हैं जैसे कि (3 * 5 + 8 - 7)/4 - 4', और गैर-प्रकार से जुड़े गैर-निर्भर कॉल के लिए अधिभार संकल्प के साथ अजीब रूप से बातचीत करता है टेम्पलेट तर्क, इसलिए उन्होंने इसे केवल डीआर में शाब्दिक शून्य में बदल दिया। –

+0

@ टी.सी. यह इंगित करने के लिए धन्यवाद, मेरा जवाब अपडेट किया गया। –

+0

वाह यह कुछ प्रमुख कोड ब्रेकेज है जिसमें उन्होंने मतदान किया। –

2

प्रति [conv.ptr]/1 (N4296 यहाँ के हवाले से):

एक नल पॉइंटर निरंतर एक पूर्णांक शाब्दिक (2.13.2) मान शून्य या प्रकार std::nullptr_t के prvalue के साथ है। ... अभिन्न प्रकार के एक शून्य सूचक स्थिर को std::nullptr_t के प्रकार के रूप में परिवर्तित किया जा सकता है।

constexpr shared_ptr(nullptr_t) noexcept : shared_ptr() { } 

जो एक खाली, गैर मालिक shared_ptr निर्माण करती है:

shared_ptr एक गैर स्पष्ट निर्माता है कि [util.smartptr.shared.const]/1 प्रति std::nullptr_t स्वीकार करता है।

जब आप f(0) सीधे कॉल, 0 एक नल पॉइंटर निरंतर कि परोक्ष ऊपर निर्माता द्वारा shared_ptr<int> में बदल जाती है है। जब आप call_f(f, 0) पर कॉल करते हैं, तो शाब्दिक 0 का प्रकार int पर घटाया जाता है और निश्चित रूप से int को shared_ptr<int> में परिवर्तित नहीं किया जा सकता है।

1

एफआईआर कॉल एफ (0) को एफ (नलप्टर) के रूप में संकलित किया गया है, जो संकलक के लिए ठीक है (लेकिन यह मेरी राय में नहीं होना चाहिए)। दूसरी कॉल किसी भी इंट पर काम करने के लिए एक समारोह के लिए घोषणा करेगी, जो अवैध है।

f(3-3); 
f(3*0); 
+0

हां, ऊपर दिए गए उत्तरों को पढ़ने के बाद यह समझ में आता है। कोड 'एफ (3-3) 'ठीक है, क्योंकि' 3-3' या '3 * 0' का मूल्यांकन 0 से मूल्यांकन किया गया है।" एक शून्य सूचक स्थिरांक एक अभिन्न निरंतर अभिव्यक्ति (5.1 9) पूर्णांक प्रकार का प्रसार है जो कि शून्य या एक प्रकार का मूल्य std :: nullptr_t का मूल्यांकन करता है। " दूसरी तरफ, 'int x = 0; एफ (एक्स); 'अब और काम नहीं करेगा, क्योंकि' x' अब 0 प्रवाल नहीं है लेकिन एक लालसा है, इसलिए अब एक शून्य सूचक स्थिर नहीं है। – vsoftco

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