2012-11-02 16 views
6

बिना चाल/प्रतियां eliding जबकि प्रकार का निष्कर्ष निकालते निम्नलिखित सरल make_pair वर्ग पर विचार करें:एक मैक्रो

struct C 
{ 
    C(int n_) : n(n_) {}; 
    C(const C& x) { n = x.n; std::cout << "Copy: " << n << std::endl; } 
    C(C&& x)  { n = x.n; std::cout << "Move: " << n << std::endl; } 
    int n; 
}; 

:

template <class X, class Y> 
struct Pair 
{ 
    X x; 
    Y y; 
}; 

इसके अलावा, हम किसी भी चलता रहता है/प्रतियां दिखाने के लिए एक सरल वर्ग बना देंगे हम तो चला सकते हैं:

auto z1 = Pair<C, C>{C(1),C(2)}; 

और कोई उत्पादन है, C नहीं है स्थानांतरित या कॉपी किया गया।

हालांकि, हमें निर्माता Pair में प्रकार निर्दिष्ट करना होगा। आइए कहें कि हम इन्हें अनुमानित करना चाहते हैं। हम कुछ इस तरह कर सकता है:

template <class X, class Y> 
Pair<X, Y> make_pair(X&& x, Y&& y) 
{ 
    return Pair<X, Y>{std::forward<X>(x), std::forward<Y>(y)}; 
} 

और फिर हम कर सकते हैं:

auto z2 = make_pair(C(3),C(4)); 

लेकिन इस प्रिंट:

Move: 3 
Move: 4 

नहीं एक समस्या है, तो C एक ढेर आवंटित प्रकार है, लेकिन यदि एक स्टैक आवंटित प्रकार, एक चाल मूल रूप से एक प्रति है।

#define MAKE_PAIR(x,y) decltype(make_pair(x,y)){x,y} 

तो हम क्या कर सकते हैं:

लेकिन फिर इस मैक्रो परिभाषित करने देता है

auto z3 = MAKE_PAIR(C(5),C(6)); 

और इस प्रकार कटौती करता है और एक कदम की जरूरत नहीं है। लेकिन हमें एक मैक्रो बनाने की जरूरत है, जो मुझे लगता है कि थोड़ा गन्दा है, और हमें इस तरह की चीज करने के लिए ऑपरेटरों का उपयोग करने से रोकता है।

क्या कोई समाधान है कि करता है निम्नलिखित:

(1) प्रकार deduces (जैसे 2 और 3)
(2) एक प्रति की आवश्यकता है या नहीं चलता (जैसे 1 और 3)
(3) मैक्रो की आवश्यकता नहीं है (जैसे 1 और 2)

सबसे अच्छा मैं तीन में से दो प्राप्त कर सकता हूं, लेकिन निश्चित रूप से तीन में से तीन संभव है? मैं कल्पना नहीं कर सकता कि सी ++ मैक्रोज़ का उपयोग करने के लिए मैक्रोज़ का उपयोग करने के लिए मजबूर होगा, क्योंकि स्पष्ट रूप से सी ++ मैक्रोज़ से दूर जा रहा है।

कोड here है।

+2

[मैं इसे प्रतियों के लिए बना सकता हूं] (http://liveworkspace.org/code/fab73a188be2b1b2bcf244dba4047b8f), चाल के बारे में निश्चित नहीं है। (ध्यान दें: यदि आप अंतराल पास करते हैं तो आपका 'मेक_पैयर' एक 'जोयर ' बनाएगा।) इस तरह, कोई प्रतियां नहीं।) – Xeo

+1

यदि आपकी स्टैक-आधारित कक्षाएं इतनी बड़ी हैं कि यह एक समस्या है, तो आप इसे गलत कर रहे हैं । – Puppy

+0

@Xeo: हे, मैं सोच रहा था कि क्या यह डिज़ाइन द्वारा था या अगर मुझे कुछ कहना चाहिए। उस निर्माता फ़ंक्शन में थोड़ा 'remove_reference' या' decay' अच्छी तरह से हो सकता है। –

उत्तर

1

मैं सी कल्पना नहीं कर सकते ++, मैक्रो का उपयोग करने के लिए जाहिरा तौर पर सी ++ मैक्रो से दूर चल रहा है के रूप में व्यवहार मैं के बाद था पाने के लिए एक मजबूर होना पड़ा।

आपके बाद के व्यवहार को पहले स्थान पर मानक द्वारा कभी गारंटी नहीं दी गई थी। Elision एक अनुकूलन है; किसी भी कार्यान्वयन के लिए यह आवश्यक नहीं है। इसलिए उनमें से कोई भी आप जो चाहते हैं उसे करने की गारंटी नहीं देता है, हालांकि स्पष्ट रूप से उनमें से कुछ कम से कम इसे संभव होने की अनुमति देते हैं।

आगे बढ़ने से एलिजन असंभव हो जाता है; उस तथ्य के बारे में कुछ भी नहीं किया जा सकता है।बिल्कुल सही अग्रेषण संदर्भ और संदर्भ ढहने के बारे में है; elision मूल्य मानकों को शुरू करने वाले मानों के बारे में है, जिसे प्रारंभिक कॉल साइट पर नहीं पता है।

वास्तविक दुनिया की स्थितियों में, यह कोई मुद्दा नहीं होना चाहिए। वास्तव में चीजों को लायक करने वाली अधिकांश चीजें ऐसी चीजें हैं जहां प्रतिलिपि महंगा है। कुछ int एस या floats की प्रतिलिपि बनाना, विशेष रूप से एक छोटी कक्षा के लिए, शायद प्रोफाइलर पर एक ब्लिप के रूप में भी दिखाई नहीं देगा। अधिकांश मामलों में, प्रतिलिपि बनाने वाली महंगी वस्तुएं इसलिए होती हैं क्योंकि वे किसी प्रकार का संसाधन रखते हैं, जैसे कि आवंटित स्मृति। इसलिए कॉपी करने के लिए महंगे अधिकांश प्रकार भी चलने योग्य हो सकते हैं, और इस प्रकार सस्ते में स्थानांतरित हो सकते हैं।

किसी भी मामले में, हाँ, यदि आप elision की संभावना चाहते हैं, तो आप अग्रेषण का उपयोग नहीं कर सकते हैं।

0

आपके उदाहरण में, आपको अभी भी एक बार प्रकार निर्दिष्ट करना है। कि इस भले ही आप और अधिक जटिल constuctors है काम करता है

auto z = Pair<C,C>{3,4}; 

नोट::

struct C { 
    C(int,int) { } 
    C(int) { } 
}; 

auto z = Pair<C,C>{{1,2},3}; 

और कोई प्रतियां की आवश्यकता है अपने लक्ष्य को एक बार से अधिक प्रकार निर्दिष्ट करने के लिए होने से बचने के लिए है, तो आप ऐसा कर सकते हैं ।

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

  • कोई संबंधित समस्या नहीं^_^