यह कहा गया काम नहीं करेगा, क्योंकि list.begin()
प्रकार है const T *
, और कोई रास्ता नहीं है जिससे आप एक स्थिर ऑब्जेक्ट से स्थानांतरित कर सकते हैं। भाषा डिजाइनरों ने संभवत: ऐसा किया ताकि इनिशियल लिस्ट को उदाहरण के लिए स्ट्रिंग स्थिरांक को शामिल करने की अनुमति दी जा सके, जिससे इसे स्थानांतरित करना अनुचित होगा।
हालाँकि, यदि आप ऐसी स्थिति में हैं, जहाँ आप जानते हैं कि इनिशियल लिस्ट में व्याप्त भाव हैं (या आप उपयोगकर्ता को लिखने के लिए बाध्य करना चाहते हैं) तो एक ट्रिक है जिससे यह काम करेगा (मैं सुमंत के उत्तर से प्रेरित था) यह, लेकिन समाधान उस की तुलना में सरल है)। आपको प्रारंभिक सूची में संग्रहीत तत्वों को T
मानों की नहीं , बल्कि मूल्यों की आवश्यकता होती है जो एनकैप्सुलेट करते हैं T&&
। फिर भले ही वे मूल्य स्वयं const
योग्य हों, फिर भी वे एक परिवर्तनशील परिवर्तन को पुनः प्राप्त कर सकते हैं।
template<typename T>
class rref_capture
{
T* ptr;
public:
rref_capture(T&& x) : ptr(&x) {}
operator T&& () const { return std::move(*ptr); } // restitute rvalue ref
};
अब initializer_list<T>
आप एक तर्क की घोषणा करने के बजाय एक तर्क की घोषणा करते initializer_list<rref_capture<T> >
हैं। यहां एक ठोस उदाहरण है, जिसमें std::unique_ptr<int>
स्मार्ट पॉइंटर्स का एक वेक्टर शामिल है , जिसके लिए केवल मूवमेंट को परिभाषित किया गया है (इसलिए ये ऑब्जेक्ट्स को इनिशियलाइज़र लिस्ट में कभी स्टोर नहीं किया जा सकता है); फिर भी समस्या के बिना संकलनकर्ता सूची नीचे दी गई है।
#include <memory>
#include <initializer_list>
class uptr_vec
{
typedef std::unique_ptr<int> uptr; // move only type
std::vector<uptr> data;
public:
uptr_vec(uptr_vec&& v) : data(std::move(v.data)) {}
uptr_vec(std::initializer_list<rref_capture<uptr> > l)
: data(l.begin(),l.end())
{}
uptr_vec& operator=(const uptr_vec&) = delete;
int operator[] (size_t index) const { return *data[index]; }
};
int main()
{
std::unique_ptr<int> a(new int(3)), b(new int(1)),c(new int(4));
uptr_vec v { std::move(a), std::move(b), std::move(c) };
std::cout << v[0] << "," << v[1] << "," << v[2] << std::endl;
}
एक प्रश्न के उत्तर की आवश्यकता होती है: यदि इनिशियलाइज़र सूची के तत्वों को सही मूल्य (उदाहरण में वे xvalues हैं) होना चाहिए, तो क्या भाषा यह सुनिश्चित करती है कि संबंधित अस्थायी लोगों का जीवनकाल उस बिंदु तक फैले जहां वे उपयोग किए जाते हैं? सच कहूं, तो मुझे नहीं लगता कि मानक खंड 8.5 के प्रासंगिक खंड इस मुद्दे को बिल्कुल भी संबोधित करते हैं। हालाँकि, 1.9: 10 को पढ़ते हुए, ऐसा लगता है कि सभी मामलों में प्रासंगिक पूर्ण-अभिव्यक्ति आरंभीकरण सूची के उपयोग को समाहित करती है, इसलिए मुझे लगता है कि प्रतिद्वंद्वियों के संदर्भ को खतरे में डालने का कोई खतरा नहीं है।
initializer_list<T>
हैं गैर -const। जैसे, वस्तुओंinitializer_list<int>
को संदर्भित करता हैint
। लेकिन मुझे लगता है कि यह एक दोष है - यह इरादा है कि संकलक केवल स्मृति में पढ़ने के लिए एक सूची आवंटित कर सकते हैं।