ไม่ได้บันทึกตัวแปร constexpr
รหัสต่อไปนี้ไม่ได้รวบรวมเป็นเสียงดัง (ทำใน GCC):
struct A{
int a;
};
auto test(){
constexpr A x{10};
return []{
return x; // <-- here x is A: clang doesn't compile
}();
}
ข้อผิดพลาดของ Clang คือตัวแปร 'x' ไม่สามารถบันทึกโดยปริยายในแลมบ์ดาโดยไม่มีการระบุค่าเริ่มต้นการจับภาพแต่ฉันคิดว่าตัวแปร constexpr ถูกจับเสมอ
ถ้า x เป็น int โค้ดจะคอมไพล์:
auto test(){
constexpr int x{10};
return []{
return x; // <-- here x is int: clang is ok
}();
}
ที่น่าสนใจรหัสต่อไปนี้ยังรวบรวม:
auto test(){
constexpr A x{10};
return []{
return x.a;
}();
}
เสียงดังใช่มั้ย? ถ้าเป็นเช่นนั้นเหตุผลคืออะไร? ฉันใช้ -std = c ++ 17
- แก้ไข -
คำถามต่อไปนี้: ฉันสามารถใช้ค่า constexpr ในแลมบ์ดาโดยไม่ต้องจับค่าได้หรือไม่ ไม่เกี่ยวข้องกับอันนี้เช่นเดียวกับ clang11 มันไม่ใช่ปัญหาอีกต่อไปในความเป็นจริงตามที่ระบุไว้ข้างต้นถ้า x เป็น int clang11 จะคอมไพล์
โค้ดตัวอย่างมีอยู่ใน https://godbolt.org/z/rxcYjz
คำตอบ
เมื่อคุณreturn x;ในตัวอย่างแรกคุณจะต้องเรียกA's ตัวสร้างสำเนาที่เกี่ยวข้องกับการผูกพันการอ้างอิงไปxและทำให้ ODR-ใช้มัน อาร์กิวเมนต์สามารถทำให้ได้ว่าสำเนาเล็กน้อยของค่าที่สามารถใช้งานได้ในนิพจน์คงที่ไม่ควรเป็นการใช้งานแบบแปลก ๆ มากกว่าreturn x.a;แต่ไม่มีข้อยกเว้นในกฎดังกล่าวดังนั้น Clang จึงถูกต้องที่จะปฏิเสธ
แน่นอนว่าคุณสามารถสร้างconstexprตัวแปรใด ๆ ก็ได้staticเพื่อหลีกเลี่ยงความจำเป็นในการจับมัน