5

मैं एक कक्षा को डिजाइन करने की कोशिश कर रहा हूं जिसमें बड़े अनुक्रमों के दो वैक्टर हैं।मैं एक टेम्पलेटेड कन्स्ट्रक्टर कैसे बना सकता हूं जो एल-वैल्यू रेफरी, आर-वैल्यू रेफरी और प्रारंभकर्ता_लिस्ट की अनुमति देता है?

std::vector<double> factory() { 
    return std::vector<double>{1,2,3}; // it actually generates a large sequence of double 
} 

struct my_class { 
    my_class(const std::vector<double>& x, const std::vector<double>& y) 
    : m_x(x), m_y(y) 
    { } 

    std::vector<double> m_x; 
    std::vector<double> m_y; 
}; 

int main() { 
    my_class c(factory(), factory()); 
    my_class c2(factory(), {0.5, 1, 1.5}); 
} 

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

struct my_class { 
    template<typename X, typename Y> 
    my_class(X&& x, Y&& y 
      , typename std::enable_if<std::is_convertible<X, std::vector<double> >::value && 
             std::is_convertible<Y, std::vector<double> >::value>::type * = 0 
      ) 
    : m_x(std::forward<X>(x)), m_y(std::forward<Y>(y)) 
    { } 

    std::vector<double> m_x; 
    std::vector<double> m_y; 
}; 

और अब मुझे कोई समस्या है। जब मैं anitializer_list के साथ एक उदाहरण बनाने का प्रयास करता हूं, तो मुझे इस तरह की त्रुटि मिली।

$ g++ -W -Wall -std=gnu++0x a.cpp 
a.cpp: In function ‘int main()’: 
a.cpp:34:32: error: no matching function for call to ‘my_class::my_class(std::vector<double>, <brace-enclosed initializer list>)’ 
a.cpp:17:18: note: candidate is: my_class::my_class(const my_class&) 

मैंने सोचा था कि std::initializer_list<double>std::vector<double> के लिए परिवर्तनीय नहीं हो सकता है, लेकिन यह वास्तव में परिवर्तनीय है और मैं एक ही त्रुटि मिली जब मैं enable_if तर्क के बिना की कोशिश की। क्या मैं कुछ भूल रहा हूँ?

+0

जिज्ञासा से आप जी ++ का किस संस्करण का उपयोग कर रहे हैं? आईआईआरसी 'शुरुआतीकरण_सूची' समर्थन कई हाल के संस्करणों में अपूर्ण था। – Flexo

+0

@awoodland मैं जीसीसी 4.6.2 का उपयोग कर रहा हूँ। 'अपूर्ण' के लिए आपका क्या मतलब है? – kukyakya

उत्तर

7

पसंदीदा मुहावरा pass by value है और फिर मैन्युअल सदस्य प्रारंभकर्ता सूची के अंदर ले जाने के:

struct my_class { 
    my_class(std::vector<double> x, std::vector<double> y) 
    : m_x(std::move(x)), m_y(std::move(y)) 
    { } 

    std::vector<double> m_x; 
    std::vector<double> m_y; 
}; 

यह सब संभव तर्क के साथ काम करते हैं और यथोचित तेज हो जाएगा:

  • आप एक वेक्टर पार कर लेते हैं lvalue, वेक्टर x में कॉपी किया गया और फिर m_x में स्थानांतरित हो गया।
  • आप एक वेक्टर rvalue पार कर लेते हैं, वेक्टर x में ले जाया गया और उसके बाद m_x में फिर से स्थानांतरित हो जाएंगे।
  • यदि आप प्रारंभकर्ता सूची पास करते हैं, तो x उस सूची से प्रारंभ किया जाएगा और फिर m_x में स्थानांतरित किया जाएगा।

विकल्प सही अग्रेषण है, लेकिन है कि यह ग्राहक के लिए कठिन बना देता है पता करने के लिए वह क्या कर सकती है में:

struct my_class { 
    template<typename T, typename U> 
    my_class(T&& x, U&& y) 
    : m_x(std::forward<T>(x)), m_y(std::forward<U>(y)) 
    { } 

    std::vector<double> m_x; 
    std::vector<double> m_y; 
}; 

इसके अलावा, मैं जी में ++ चेतावनी का एक समूह मिलता है, तो मैं wouldn ' टी अनुशंसा नहीं करते हैं। बस पूर्णता के लिए इसका जिक्र है।

+0

पास-बाय-वैल्यू तर्कों की एक प्रति उत्पन्न करेगा, जो कि उपयोगकर्ता 1030861 से बचना चाहता है, अगर मैं सवाल को समझता हूं। – Gabriel

+0

@ गैब्रियल: यह तर्क की मूल्य श्रेणी पर निर्भर करता है। यदि तर्क एक रावल्यू है, तो मान द्वारा कॉल * तर्क * चाल * कॉपी नहीं करेगा। एक प्रति केवल तभी किया जाता है जब तर्क एक लालसा है। – fredoverflow

+0

@ गैब्रियल: मेरे उत्तर को और अधिक विस्तृत स्पष्टीकरण के साथ अपडेट किया गया। क्या उससे मदद हुई? – fredoverflow

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