2012-12-30 15 views
5

मान लीजिए इस प्रकार हम एक वर्ग बॉक्स है:उचित भंडारण मूल्य प्रकार प्राप्त करना?

struct Base {} 

template<typename T> 
struct Box : Base 
{ 
    template<typename... Args> 
    Box(Args&&... args) 
     : t(forward<Args>(args)...) 
    {} 

    T t; 
} 

और फिर हम एक समारोह MakeBox है:

template<typename X> 
Base* MakeBox(X&& x) 
{ 
    return new Box<???>(forward<X>(x)); 
} 

प्रकार X MakeBox करने के लिए कॉल में इस्तेमाल किया पैरामीटर से निष्कर्ष निकाला है।

हम तो मुझे लगता है कि अगर हम सिर्फ भोलेपन का उपयोग उचित "भंडारण प्रकार" पैरामीटर टी

एक्स से किसी भी तरह की गणना करने की जरूरत है:

return new Box<X>(forward<X>(x)); 

तो यह समस्याएं होंगी।

स्पष्ट रूप से std::bind और std::function इन समस्याओं से निपटने की आवश्यकता है, वे इसे कैसे करते हैं?

std::decay वैसे भी यहां सहायक है?

+0

नहीं है ['std :: remove_reference '] (http://en.cppreference.com/w/cpp/types/remove_reference) जो आप खोज रहे हैं? – jogojapan

+0

@jogojapan: क्या यह 'std :: bind' अपने बाध्य पैरामीटर को स्टोर करने के लिए उपयोग करता है? –

+3

'std :: decay' वही है जो आप खोज रहे हैं। – Mankarse

उत्तर

1

प्रदान किए गए उदाहरण के लिए (1) वह वही करता है जो आप चाहते हैं और मूल्य को स्टोर करते हैं। अन्य मामलों के लिए (जैसे कि जब x एक सरणी है) तो आप std::decay का उपयोग किसी सूचक को क्षय करने और स्टोर करने के लिए कर सकते हैं।

3

यदि मैं सही ढंग से समझता हूं कि आप क्या हासिल करना चाहते हैं, तो आपको std::decay का उपयोग करने की आवश्यकता है। मान लीजिए कि आप S से MakeBox() पर ऑब्जेक्ट की आपूर्ति कर रहे हैं, सार्वभौमिक संदर्भ X&& को किसी भी तरह से S& या S&& प्रकार का कार्य तर्क बनाने के लिए इस तरह से हल किया जाएगा कि आपका तर्क (क्रमशः) एक लालसा या रावल्यू है या नहीं।

इस लक्ष्य को हासिल करने के लिए और कारण सार्वभौमिक संदर्भ के लिए सी ++ 11 नियम, पहले मामले में टेम्पलेट तर्क, क्योंकि आपके सदस्य चर के लिए है X=S& (यहाँ X के रूप में निष्कर्ष निकाला की जाएगी Box<> लिए एक तर्क के रूप ठीक नहीं होगा करने के लिए एक वस्तु हो और ऑब्जेक्ट संदर्भ न हो), जबकि दूसरे मामले में इसे X=S के रूप में घटाया जाएगा (यहां XBox<> पर तर्क के रूप में ठीक होगा)। std::decay लागू करके आप भी परोक्ष std::remove_reference deduced प्रकार X को Box<> के लिए एक टेम्पलेट तर्क के रूप में यह आपूर्ति से पहले लागू होगी, तो आप यह सुनिश्चित करें कि X हमेशा समान S और कभी नहीं S& (कृपया ध्यान रखें हो जाएगा बनाने जा रहे हैं, कि Xहै को S&& के रूप में कभी भी घटाया जा रहा है, यह या तो S या S& होगा)।

Scott Meyers on universal references

पुनश्च:: इस उत्तर संपादित किया गया है: अपने मूल

#include <utility> 
#include <type_traits> 
#include <iostream> 

using namespace std; 

struct Base {}; 

template<typename T> 
struct Box : Base 
{ 
    template<typename... Args> 
    Box(Args&&... args) 
     : t(forward<Args>(args)...) 
    { 
    } 

    T t; 
}; 

template<typename X> 
Base* MakeBox(X&& x) 
{ 
    return new Box<typename decay<X>::type>(forward<X>(x)); 
} 

struct S 
{ 
    S() { cout << "Default constructor" << endl; } 
    S(S const& s) { cout << "Copy constructor" << endl; } 
    S(S&& s) { cout << "Move constructor" << endl; } 
    ~S() { cout << "Destructor" << endl; } 
}; 

S foo() 
{ 
    S s; 
    return s; 
} 

int main() 
{ 
    S s; 

    // Invoking with lvalue, will deduce X=S&, argument will be of type S& 
    MakeBox(s); 

    // Invoking with rvalue, will deduce X=S, argument will be of type S&& 
    MakeBox(foo()); 

    return 0; 
} 

आप रुचि रखते हैं, यहाँ है, जहाँ वे बताते हैं स्कॉट Meyers द्वारा एक बहुत अच्छा सबक कैसे सार्वभौमिक संदर्भ व्यवहार करते है उत्तर std::remove_reference<> का उपयोग करने के लिए सुझाव दिया गया है, लेकिन std::decay बेहतर विकल्प बन गया है।प्रश्न पोस्टर @ एंड्रू टॉमज़ोस फाथोमलिंग कॉरप्स को क्रेडिट, जिन्होंने इंगित किया, और @ मंकर्स, जिन्होंने पहले मूल प्रश्न पर टिप्पणी में इसका प्रस्ताव दिया था।

+0

'std :: decay' के बारे में क्या? –

+0

वास्तव में 'std :: decay' एक अच्छा विकल्प प्रतीत होता है, शायद यह भी बेहतर है क्योंकि इसमें' std :: remove_reference <> 'भी शामिल है। जिस कारण से मैंने शुरुआत में इसे नहीं माना था, वह यह है कि यह 'कॉन्स' क्वालीफायर को हटा देता है, लेकिन तब मुझे एहसास हुआ कि शायद आप 'कॉन्स्ट' क्वालीफायर को बिल्कुल नहीं रखना चाहते हैं, क्योंकि आप अंदर एक नई वस्तु बना रहे हैं 'बॉक्स' का और इसकी प्रतिलिपि कन्स्ट्रक्टर को बुला रहा है। यदि ऐसा है, तो हम वास्तव में 'std :: remove_reference' को मेरे उत्तर में' std :: decay' के साथ प्रतिस्थापित कर सकते हैं। मैं ऐसा करूँगा और उचित क्रेडिट दूंगा। –

+0

बीटीडब्ल्यू, कार्य 'मेकबॉक्स <>()' और वर्ग 'बॉक्स <>' से संबंधित है, क्या आप वाकई हमेशा 'टी' की कॉपी कन्स्ट्रक्टर को कॉल करना चाहते हैं? 'टी' के निर्माता को तर्कों को आगे बढ़ाने के लिए आपके पास 'बॉक्स <>' के निर्माता में एक तर्क पैक है, लेकिन आप हमेशा इनपुट में केवल एक 'टी' ऑब्जेक्ट पास कर रहे हैं, इसलिए यह हमेशा कॉपी कन्स्ट्रक्टर को आमंत्रित करता है। क्या आपके पास 'मेकबॉक्स <>() 'में एक भिन्न सूची नहीं होनी चाहिए? बीटीडब्ल्यू, बेस * लौटने की बजाय * मैं सटीक सूचक ('बॉक्स <टाइपनाम std :: क्षय :: प्रकार> * ') –

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