Mã dưới đây thể hiện hành vi của gcc 4.6.2 mà tôi không thể giải thích. Hàm đầu tiên khai báo một mảng tĩnh kiểu vec_t, trong đó vec_t là một bí danh typedef'd cho unsigned char. Hàm thứ hai giống hệt nhau, ngoại trừ loại vect_t là một tham số mẫu. Lỗi thứ hai không thể biên dịch với chẩn đoán ": kích thước bộ nhớ của‘ bitVec ’không cố định".Lỗi trình biên dịch? g ++ cho phép các mảng tĩnh có kích thước thay đổi, trừ khi hàm được templated
#include <limits>
void bitvec_func()
{
const std::size_t nbits = 1e7;
typedef unsigned char vec_t;
const std::size_t WLEN = std::numeric_limits<vec_t>::digits;
const std::size_t VSIZ = nbits/WLEN+1;
static vec_t bitVec[nbits/VSIZ]; // Compiles fine
}
template <typename T>
void bitvec_func()
{
const std::size_t nbits = 1e7;
typedef T vec_t;
const std::size_t WLEN = std::numeric_limits<vec_t>::digits;
const std::size_t VSIZ = nbits/WLEN+1;
static vec_t bitVec[nbits/VSIZ]; // "error: storage size of ‘bitVec’ isn’t constant"
}
void flarf()
{
bitvec_func();
bitvec_func<unsigned char>();
}
Dường như với tôi rằng việc tạo mẫu với đối số < unsigned char> sẽ khiến trình biên dịch tạo mã giống như hàm đầu tiên. Bất cứ ai có thể cung cấp bất kỳ cái nhìn sâu sắc vào lý do tại sao điều này dường như không phải là trường hợp?
[Phụ lục: hàm thứ hai sẽ biên dịch với "-std = C++ 0x" hoặc "-std = gnu ++ 0x", nhưng tôi vẫn muốn hiểu cách/nếu nó sai theo định nghĩa ngôn ngữ trước đó]
ETA:.
chức năng thứ hai sẽ biên dịch nếu initializer cho nbits được thay đổi:
const std::size_t nbits = 1e7; // Error
const std::size_t nbits = (std::size_t)1e7; // Okay
const std::size_t nbits = 10000000.0; // Error
const std::size_t nbits = 10000000; // Okay
Nói cách khác, có vẻ như rằng nếu nbits
được khởi tạo với một biểu hiện của một thể thiếu loại, sau đó nbits
được coi là liên tục trong định nghĩa của bitVec
. Nếu nbits
thay vào đó được khởi tạo với biểu thức dấu phẩy động, trình biên dịch sẽ không còn nhìn thấy nó dưới dạng hằng số trong biểu thức cho thứ nguyên của bitVec
và quá trình biên dịch không thành công.
Tôi gọi rất ít "lỗi trình biên dịch" trong C++ hơn tôi sẽ ở trong C, nhưng tôi không thể nghĩ ra bất kỳ lý do nào khác khiến 4 trường hợp trên không giống hệt về mặt ngữ nghĩa. Bất cứ ai khác quan tâm đến opine?
Bạn có thể đăng mã chính xác cho bạn lỗi trình biên dịch không? Tôi không thể tái tạo nó. –
Đó là mã chính xác ở trên. Trình biên dịch là gcc 4.6.2 và các tùy chọn là "-O0 -g3 -c". –
Trên gcc cũ hơn 4.3.4, mã này [biên dịch tốt] (http://ideone.com/65Cl7). –