2012-06-09 53 views
11

Tôi dường như thiếu một thứ gì đó khá cơ bản. Tôi đang cố gắng sử dụng các thành viên mảng const tại thời gian biên dịch.Hằng số mảng thời gian biên dịch

const int list[3] = { 2, 5, 7 }; 
const int a = list[2]; // this doesn't error? 

template<int N1, int N2> 
struct tmax { 
    enum { value = ((N1 > N2) ? N1 : N2) }; 
}; 

const int b = tmax<2,4>::value; 
const int c = tmax<list[0],list[1]>::value; // error is here 

int main() 
{ 
    return 0; 
} 

Lỗi:

prog.cpp:10:24: error: 'list' cannot appear in a constant-expression 
prog.cpp:10:30: error: an array reference cannot appear in a constant-expression 

Đây là relevent IDEOne link

Vậy tại sao không làm việc này? Tôi đang thiếu gì? Tôi nên làm gì khác?

Trả lời

9

Chỉ vì một đối tượng là const không có nghĩa đó là biểu thức hằng số thời gian biên dịch.

main.cpp:10:20: error: non-type template argument is not a constant expression 
const int c = tmax<list[0],list[1]>::value; // error is here 
        ^~~~~~~ 
main.cpp:10:20: note: read of non-constexpr variable 'list' is not allowed in a constant expression 
main.cpp:1:11: note: declared here 
const int list[3] = { 2, 5, 7 }; 
     ^

Đây là lý do cho constexpr:

constexpr int list[3] = { 2, 5, 7 }; 

template<int N1, int N2> 
struct tmax { 
    enum { value = ((N1 > N2) ? N1 : N2) }; 
}; 

const int b = tmax<2,4>::value; 
const int c = tmax<list[0],list[1]>::value; // works fine now 

Đối với lý do tại sao công trình này:

const int a = list[2]; // this doesn't error? 

khởi tạo một biến const không đòi hỏi một biểu thức hằng:

int foo(int n) { 
    const int a = n; // initializing const var with a non-compile time constant 
+0

Tôi đã tìm ra constexpr sẽ hữu ích, và bây giờ tôi thấy tôi thấy nó có sự chấp nhận rộng hơn tôi nghĩ. Với điều đó đã nói, một chút giải thích về lý do tại sao việc khai báo const int một tác phẩm nhưng danh sách [1] đặc biệt sẽ không được đánh giá cao. Cảm ơn bạn. –

+0

OK, vì vậy studio trực quan 2012 không có kế hoạch hỗ trợ constexpr. Bất cứ ai có bất kỳ giải pháp khác? Tôi KHÔNG PHẢI sử dụng nó cho việc này, nhưng nó sẽ rất tuyệt. –

+0

@ std''OrgnlDave Tôi đã thêm nhiều chẩn đoán trình biên dịch giải thích chính xác lý do danh sách [1] không phải là biểu thức liên tục. – bames53

4

Biểu thức không phải là biểu thức hằng số nếu chúng chứa bất kỳ một trong số các biểu thức phụ không được phép. Một trong những loại không được phép tiểu biểu là:

  • một giá trị trái-to-rvalue chuyển đổi (4.1) trừ khi nó được áp dụng cho
    • một glvalue của thiếu hoặc liệt kê kiểu đó đề cập đến một tổ chức phi -volatile đối tượng const với trước khởi, khởi tạo với một biểu thức hằng số, hoặc
    • một glvalue loại đen đó đề cập đến một đối tượng non-volatile định nghĩa với constexpr, hoặc là đề cập đến một sub-object của một đối tượng như vậy hoặc
    • một glvalue kiểu chữ đề cập đến một đối tượng tạm thời không bay hơi có tuổi thọ không kết thúc, được khởi tạo với biểu thức không đổi;

Đặc biệt, trong khi tên của một đối tượng const của enum hoặc loại intergral khởi tạo với một initializer liên tục tạo thành một biểu thức hằng (đọc giá trị của nó là những gì gây ra vế trái-to-rvalue chuyển đổi), các đối tượng con của một đối tượng tổng hợp const (chẳng hạn như list trong ví dụ của bạn, một mảng) không, nhưng sẽ nếu khai báo constexpr.

const int list[3] = { 2, 5, 7 }; 
const int a = list[2]; 

Đây là hợp lệ nhưng a không cấu thành một hằng số biểu hiệnbởi vì nó không được khởi tạo với một biểu thức hằng .

Bằng cách thay đổi khai báo list (chúng tôi không phải thay đổi tuyên bố a), chúng tôi có thể làm cho a tạo thành biểu thức không đổi.

constexpr int list[3] = { 2, 5, 7 }; 
const int a = list[2]; 

Như list[2] tại là một hằng số biểu hiện, a bây giờ là một đối tượng const loại intergral khởi tạo với một biểu thức hằng nên a bây giờ có thể được sử dụng như một biểu thức hằng.

+0

Nó gần như làm cho tôi khóc rằng visual studio 2k12 sẽ không hỗ trợ constexpr. Tôi đã không bao giờ được sử dụng mảng như thế này trong mẫu metaprogramming nhưng tôi rất mong nó ... –

Các vấn đề liên quan