สิ่งนี้จะไม่ทำงานตามที่ระบุไว้เนื่องจากlist.begin()
มีประเภทconst T *
และไม่มีทางที่คุณจะย้ายจากวัตถุคงที่ได้ นักออกแบบภาษาอาจทำเช่นนั้นเพื่อให้รายการเริ่มต้นมีค่าคงที่ของสตริงซึ่งจะไม่เหมาะสมที่จะย้าย
อย่างไรก็ตามหากคุณอยู่ในสถานการณ์ที่คุณรู้ว่ารายการ initializer มีนิพจน์ rvalue (หรือคุณต้องการบังคับให้ผู้ใช้เขียนสิ่งเหล่านั้น) มีเคล็ดลับที่จะทำให้มันใช้งานได้ (ฉันได้รับแรงบันดาลใจจากคำตอบของ Sumant สำหรับ แต่วิธีแก้ปัญหานั้นง่ายกว่าวิธีนั้น) คุณจำเป็นต้องมีองค์ประกอบที่เก็บไว้ในรายการ initialiser ที่จะไม่ได้T
ค่า T&&
แต่ค่าที่แค็ปซูล จากนั้นแม้ว่าค่าเหล่านั้นจะconst
มีคุณสมบัติเหมาะสม แต่ก็ยังสามารถดึงค่า rvalue ที่ปรับเปลี่ยนได้
template<typename T>
class rref_capture
{
T* ptr;
public:
rref_capture(T&& x) : ptr(&x) {}
operator T&& () const { return std::move(*ptr); }
};
ตอนนี้แทนที่จะประกาศinitializer_list<T>
อาร์กิวเมนต์คุณประกาศinitializer_list<rref_capture<T> >
อาร์กิวเมนต์ นี่คือตัวอย่างที่เป็นรูปธรรมซึ่งเกี่ยวข้องกับเวกเตอร์ของพstd::unique_ptr<int>
อยน์เตอร์อัจฉริยะซึ่งกำหนดเฉพาะความหมายการย้าย (ดังนั้นอ็อบเจ็กต์เหล่านี้จะไม่สามารถเก็บไว้ในรายการตัวเริ่มต้น) แต่รายการ initializer ด้านล่างรวบรวมได้โดยไม่มีปัญหา
#include <memory>
#include <initializer_list>
class uptr_vec
{
typedef std::unique_ptr<int> uptr;
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;
}
คำถามหนึ่งข้อต้องการคำตอบ: หากองค์ประกอบของรายการตัวเริ่มต้นควรเป็น prvalues จริง (ในตัวอย่างคือ xvalues) ภาษาจะทำให้แน่ใจได้หรือไม่ว่าอายุการใช้งานของโมเมนต์ที่เกี่ยวข้องจะขยายไปจนถึงจุดที่ใช้ ตรงไปตรงมาฉันไม่คิดว่ามาตรา 8.5 ที่เกี่ยวข้องของมาตรฐานจะช่วยแก้ปัญหานี้ได้เลย อย่างไรก็ตามเมื่ออ่าน 1.9: 10 ดูเหมือนว่านิพจน์ทั้งหมดที่เกี่ยวข้องในทุกกรณีจะครอบคลุมการใช้รายการตัวเริ่มต้นดังนั้นฉันคิดว่าไม่มีอันตรายจากการอ้างอิงค่า rvalue ที่ห้อยลงมา
initializer_list<T>
มีไม่ใช่ -const ชอบinitializer_list<int>
หมายถึงint
วัตถุ แต่ฉันคิดว่านั่นเป็นข้อบกพร่อง - มีจุดมุ่งหมายเพื่อให้คอมไพเลอร์สามารถจัดสรรรายการในหน่วยความจำแบบอ่านอย่างเดียวแบบคงที่