2011-11-22 39 views
5

Tôi có đoạn mã sau:Lỗi biên dịch mẫu - chuẩn hay không?

template<int k> 
void foo() 
{ 
} 
int main(int argc, char* argv[]) 
{ 
    int k = 1000; 
    foo<k>(); 
    return 0; 
} 

mà không biên dịch, nhưng nếu tôi tuyên bố k như const, nó:

template<int k> 
void foo() 
{ 
} 
int main(int argc, char* argv[]) 
{ 
    const int k = 1000; 
    foo<k>(); 
    return 0; 
} 

Bây giờ, tôi thấy logic đằng sau lý do tại sao trong lần đầu tiên trường hợp nó không biên dịch và trong trường hợp thứ hai, nhưng điều này có được quy định bởi tiêu chuẩn không?

Các lỗi tôi nhận được là:

Error 1 error C2971: 'foo' : template parameter 'k' : 'k' : a local variable cannot be used as a non-type argument 

mà không phải là chính xác rõ ràng, kể từ k là một biến địa phương cũng trong trường hợp đó là const ... phải không?

Trả lời

2

§14.3.2.1 nói [rút gọn]:

A template-argument for a non-type, non-template template-parameter shall be one of:
— an integral constant-expression of integral or enumeration type;

Và §5.19 .1 nói [rút gọn, tôi nhấn mạnh]:

An integral constant-expression can involve only literals, enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions...

định nghĩa thứ hai của bạn của k thỏa mãn này, vì vậy nó được phép sử dụng như một ICE cho mẫu tranh cãi.

Lỗi hơi gây nhầm lẫn ở chỗ "biến cục bộ không thể được sử dụng làm đối số không phải kiểu" là đúng nói chung là, nhưng với một số hạn chế, nó hoàn toàn ổn.

4

mỗi tiêu chuẩn, 14.3.2, đây phải là một biểu thức hằng:

A template-argument for a non-type, non-template template-parameter shall be one of:
an integral constant-expression of integral or enumeration type; or
— the name of a non-type template-parameter; or
— the address of an object or function with external linkage, including function templates and function template-ids but excluding non-static class members, expressed as & id-expression where the & is optional if the name refers to a function or array, or if the corresponding template-parameter is a reference; or
— a pointer to member expressed as described in 5.3.1 .

GCC 4.6.2 cung cấp cho một lỗi nhẹ dễ hiểu hơn:

error: ‘k’ cannot appear in a constant-expression

+0

Bạn không xác định lý do tại sao 'k' hoạt động trong một nhưng không phải là khác, đó là phần thịt của câu hỏi. – GManNickG

+0

Xem phần tôi đã in đậm. Tiêu chuẩn nói rằng biểu thức phải không đổi. –

+0

Nhưng tôi tự nhắc lại: bạn không giải thích tại sao 'k' có thể sử dụng được hay không. – GManNickG

2

giá trị số Const có thể được đánh giá trên thời gian biên dịch khi compilator cố gắng mở rộng các mẫu tới dạng cuối cùng. Vì vậy, giá trị thực hiện thời gian không thể tranh cãi đối với các mẫu, nhưng luôn luôn bạn có thể thiết lập tham chiếu đến biến như mẫu đối số

template<int& k> 
void foo() 
{ 
} 
int main(int argc, char* argv[]) 
{ 
    int k = 1000; 
    foo<k>(); 
    return 0; 
}