ไม่ได้บันทึกตัวแปร constexpr

Dec 10 2020

รหัสต่อไปนี้ไม่ได้รวบรวมเป็นเสียงดัง (ทำใน 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

คำตอบ

2 DavisHerring Dec 25 2020 at 07:09

เมื่อคุณreturn x;ในตัวอย่างแรกคุณจะต้องเรียกA's ตัวสร้างสำเนาที่เกี่ยวข้องกับการผูกพันการอ้างอิงไปxและทำให้ ODR-ใช้มัน อาร์กิวเมนต์สามารถทำให้ได้ว่าสำเนาเล็กน้อยของค่าที่สามารถใช้งานได้ในนิพจน์คงที่ไม่ควรเป็นการใช้งานแบบแปลก ๆ มากกว่าreturn x.a;แต่ไม่มีข้อยกเว้นในกฎดังกล่าวดังนั้น Clang จึงถูกต้องที่จะปฏิเสธ

แน่นอนว่าคุณสามารถสร้างconstexprตัวแปรใด ๆ ก็ได้staticเพื่อหลีกเลี่ยงความจำเป็นในการจับมัน