2012-09-18 15 views
7

Các mã sau đây có vẻ tốt đẹp với tôi:C2070 - bất hợp pháp sizeof toán hạng

#include <stdio.h> 

    template <typename T> 
    struct A 
    { 
     static float m_kA[]; 
    }; 

    template <typename T> 
    float A<T>::m_kA[] = {1.0f, 2.0f, 3.0f}; 

    int main() 
    { 
     printf("%d\n", 
      sizeof(A<unsigned int>::m_kA)/
      sizeof(A<unsigned int>::m_kA[0])); 
     return 0; 
    } 

Nhưng khi tôi biên dịch với VC9 tôi nhận được lỗi sau

error C2070: 'float []': illegal sizeof operand 

Tôi mong chờ mã này để biên dịch. Tui bỏ lỡ điều gì vậy? Có ai biết một cách để sửa chữa hành vi kỳ lạ này (lưu ý rằng điều tương tự chính xác mà không có mẫu biên dịch tốt và đầu ra 3).

Lưu ý rằng việc xóa mẫu không phải là một tùy chọn, tôi đã tạo ví dụ này để tạo lại sự cố mà tôi đang gặp phải trong mã mà tôi cần loại chứa mảng làm mẫu.

Cảm ơn

+1

FWIW, Biên soạn tiền phạt trên GCC 4.7.1: http://liveworkspace.org/code/19f48dbdb07463b08a310c168ab59a67. Xem đó là một lỗi MSVC khác hay gì đó. – chris

+0

Tôi không nghĩ rằng biểu thức đang tính toán những gì bạn nghĩ rằng nó đang tính toán. – Nobody

+4

@Nobody 'mảng mảng sizeof/sizeof [0]' là một thành ngữ phổ biến tính toán độ dài của mảng.Bạn nghĩ nó tính toán gì, hoặc bạn nghĩ người khác nghĩ nó tính toán cái gì? – hvd

Trả lời

4

Nó được xác định rõ. Lưu ý rằng trong định nghĩa lớp, m_kA được khai báo với loại float[], là loại không đầy đủ và không thể được sử dụng song song với sizeof. Trong định nghĩa của m_kA, nó được redeclared để có loại float[3], sau đó nó là okay để sử dụng sizeof. (8.3.4 chỉnh việc ý nghĩa của tờ khai mảng.)

Từ 3.4.6 Sử dụng-chỉ thị và bí danh namespace [basic.lookup.udir]:

10 Sau khi tất cả các điều chỉnh các loại (trong đó Typedefs (7.1.3) được thay thế bởi các định nghĩa của chúng), các kiểu được chỉ định bởi tất cả các khai báo tham chiếu đến một biến hoặc hàm nhất định phải giống nhau, ngoại trừ các khai báo cho một đối tượng mảng có thể xác định loại mảng khác nhau. mảng bị ràng buộc (8.3.4). Vi phạm quy tắc này về nhận dạng loại không yêu cầu chẩn đoán.

Từ 3.9.2 loại Compound [basic.compound]:

6 [...] Các loại tuyên bố của một đối tượng mảng có thể là một mảng có kích thước không rõ và do đó không đầy đủ tại một điểm trong một đơn vị dịch thuật và hoàn thành sau này; các kiểu mảng tại hai điểm đó (“mảng không xác định của T” và “mảng của N T”) là các kiểu khác nhau. [...]

Giải pháp cho các sự cố biên dịch của bạn sẽ là khai báo m_kA với kiểu hoàn toàn hoàn chỉnh. Một thành viên tĩnh khác có kích thước cũng có thể hữu ích.

[Tôi trích dẫn từ C++ 11 nhưng theo sự hiểu biết tốt nhất của tôi, C++ 03 tuân theo cùng các quy tắc. ]

+1

Tôi sẽ rất vui khi nội tuyến bộ khởi tạo, nếu C++ cho phép tôi làm điều đó. Vấn đề là theo như tôi biết tôi chỉ có thể làm điều đó chỉ cho các biến địa phương hoặc toàn cầu, và như vậy tôi không thể tạo một mẫu cho nó. Cũng như tôi đã nói trước khi tôi thấy khó khăn để biện minh cho VC9 trong việc này, bởi vì nếu tôi chỉ gỡ bỏ tất cả mọi thứ mẫu hoạt động. – valerio

+1

Suy nghĩ thêm một số, cấu trúc như [this] (http://pastebin.com/tumC3NBU) (lưu ý: không hợp lệ C++) là một lý do chính đáng tại sao loại * nên * có lẽ vẫn còn 'float []' chứ không phải là 'float [3] 'với các mẫu. Nhưng như chúng ta đã thấy trong cuộc thảo luận đã bị xóa, kiểu thực sự là 'float [3]'. – hvd