biến constexpr không được bắt

Dec 10 2020

Đoạn mã sau không biên dịch bằng tiếng clang (nó có trong GCC):

struct A{
    int a;
};

auto test(){
    constexpr A x{10};
    return []{
        return x; // <-- here x is A: clang doesn't compile
    }();
}

Lỗi của Clang là biến 'x' không thể được nắm bắt ngầm trong lambda mà không có mặc định chụp nào được chỉ định , nhưng tôi nghĩ rằng các biến constexpr luôn được ghi lại.

Nếu x là một int, mã sẽ biên dịch:

auto test(){
    constexpr int x{10};
    return []{
        return x; // <-- here x is int: clang is ok
    }();
}

Điều thú vị là đoạn mã sau cũng biên dịch:

auto test(){
    constexpr A x{10};
    return []{
        return x.a;
    }();
}

Là tiếng vang phải không? Nếu vậy, cơ sở lý luận là gì? Tôi đang sử dụng -std = c ++ 17

--BIÊN TẬP--

Câu hỏi sau: Tôi có thể sử dụng giá trị constexpr trong lambda mà không ghi lại nó không? không liên quan đến điều này, vì với clang11, nó không còn là vấn đề nữa: trên thực tế, như đã nêu ở trên, nếu x là int, clang11 biên dịch.

Mã mẫu cũng có trong https://godbolt.org/z/rxcYjz

Trả lời

2 DavisHerring Dec 25 2020 at 07:09

Khi bạn return x;trong ví dụ đầu tiên, bạn phải gọi hàm tạo Abản sao của, liên quan đến việc ràng buộc một tham chiếu đến xvà do đó odr-sử dụng nó. Lập luận có thể được đưa ra rằng một bản sao tầm thường của một giá trị có thể sử dụng trong các biểu thức hằng không nên tạo thành một cách sử dụng odr hơn nữa return x.a;, nhưng không có ngoại lệ nào như vậy trong quy tắc đó, vì vậy Clang đúng khi bác bỏ nó.

Như một vấn đề thực tế, tất nhiên bạn có thể thực hiện bất kỳ constexprbiến staticnào để không cần phải nắm bắt nó.