Xét đoạn mã sau:biên dịch báo lỗi khi sử dụng CRTP với static_assert
template<typename Derived>
struct Base {
static constexpr int x_base = Derived::x_derived;
//static_assert(x_base > 1, "Oops");
};
struct Derived : public Base<Derived> {
static constexpr int x_derived = 5 ;
};
Base<Derived> obj;
này biên dịch tốt trên gcc nhưng nếu tôi bỏ ghi chú dòng static_assert
, nó than phiền rằng
error: incomplete type 'Derived' used in nested name specifier
static constexpr int x_base = Derived::x_derived;
Tôi đã thử nó với nhau phiên bản của gcc từ 4,9 đến 5,3 và tôi nhận được cùng một lỗi (bạn có thể thử nó trên godbolt here). kêu vang từ chối để biên dịch nó ngay cả khi không static_assert
, và phàn nàn rằng
error: no member named 'x_derived' in 'Derived'
static constexpr int x_base = Derived::x_derived;
nào biên dịch là chính xác (nếu có)? Có cách nào tốt đẹp để sửa mã không?
Cảm ơn câu trả lời tuyệt vời Barry. Vì vậy, nếu tôi hiểu bạn một cách chính xác, thực tế là gcc chấp nhận mã mà không có static_assert là một lỗi trình biên dịch, và clang là chính xác trong việc từ chối nó? – toth
@toth gcc không từ chối nó cho đến khi bạn thực sự sử dụng nó ở bất cứ nơi nào - vì vậy nó chỉ là một chút thân thiện hơn về khía cạnh đó. Nhưng nó không thực sự có ý nghĩa để chỉ cần khai báo một biến mà bạn không bao giờ sử dụng - do đó, nó từ chối nó một cách chính xác nơi nó quan trọng. – Barry
nhưng gcc không cho phép tôi sử dụng nó, miễn là nó không nằm trong static_assert. Ví dụ: https://godbolt.org/g/rfbH5c (trong khi clang tiếp tục từ chối mã). Vì vậy, một trong những trình biên dịch phải là sai, bất kỳ ý tưởng nào? – toth