Cả gcc 5.0 và kêu vang 3.6 đòi hỏi từ khóa typename
trong ví dụ sau:Biểu thức ném hoặc xóa có bao giờ phụ thuộc không?
template<typename T>
struct B
{
typedef int Type;
};
template<int n>
struct A
{
typedef typename B<decltype(throw (int*)n)>::Type Throw;
typedef typename B<decltype(delete (int*)n)>::Type Delete;
};
này được bao phủ bởi các từ ngữ sau đây trong các tiêu chuẩn C++ 11:
[trừ]/2
Biểu thức ném có loại void.
[expr.delete]/1
Các toán hạng phải có một con trỏ đến kiểu đối tượng, hoặc một loại lớp có một đĩa đơn không rõ ràng chuyển đổi chức năng để một con trỏ đến kiểu đối tượng. Kết quả có loại void.
Vì vậy, tôi giả sử decltype
sản xuất void
trong cả hai trường hợp.
[expr.const]/2
Một điều kiện thể hiện là một biểu thức hằng lõi trừ khi nó liên quan đến một trong các cách sau như một subexpression khả năng đánh giá
mới thể hiện
một biểu thức ném
Điều này cho thấy rằng một biểu thức liên quan đến throw
hoặc delete
không được là cụm từ không đổi.
[temp.dep.type]/8
Một loại phụ thuộc nếu nó là
một đơn giản-template-id trong đó một trong hai tên mẫu là một tham số mẫu hoặc bất kỳ mẫu đối số nào trong số các đối số là một loại phụ thuộc hoặc một biểu thức phụ thuộc vào loại hoặc phụ thuộc vào giá trị
ký hiệu là
decltype(expression)
, trong đó biểu thức là loại phụ thuộc nt
Vì vậy B<decltype(..)>
phụ thuộc chỉ nếu biểu thức là gõ phụ thuộc.
[temp.dep.expr]/4
Expressions trong các hình thức sau đây không bao giờ gõ phụ thuộc (vì kiểu của biểu thức không thể phụ thuộc):
delete cast-expression throw assignment-expression
Điều này cho thấy rằng không phải biểu hiện có thể được loại phụ thuộc vào .
Gcc và clang có sai không?
Tôi không nghĩ lý do của bạn về [temp.dep.constexpr]/p1 là chính xác. Một 'reinterpret_cast' không thể xuất hiện trong một biểu thức liên tục, nhưng [temp.dep.constexpr]/p3 chỉ rõ rằng một biểu thức liên quan đến' reinterpret_cast' có thể có thể phụ thuộc vào giá trị. –
'decltype (..)' không phải là một biểu thức. Vì vậy, bạn cũng cần [temp.dep.type] /9.8 Đoạn đó chỉ yêu cầu biểu thức trong 'decltype (expression)' không phải là * type-dependent *, được chỉ rõ cho 'throw' và' new'. – dyp
@dyp Có! Điều đó dường như kết luận. – willj