2009-03-13 22 views
8

Nếu bạn đang sử dụng mẫu trong C++ có giá trị nguyên như tham số, có bất kỳ yêu cầu nào trên biến số nguyên được sử dụng làm tham số khác với biến được sử dụng làm tham số trong lệnh gọi hàm không?Các yêu cầu đối với tham số mẫu C++ là gì?

Đây là câu hỏi tiếp theo cho câu hỏi here. Tôi đặc biệt muốn giải quyết nếu có một biến WRT khác biệt được khai báo là "extern const int" cho các hàm hoặc mẫu?

Tôi có thể thấy rằng đối với một số trường hợp mẫu, giá trị tham số sẽ là cần thiết vào thời gian biên dịch. Điều này có đúng không? Có cách nào để xác định, có thể chỉ sử dụng một số giá trị tham số, mà giá trị được sử dụng trong thời gian chạy?

Trả lời

3

Luôn luôn có trường hợp giá trị của int là cần thiết tại thời gian biên dịch.

Vì mỗi bản mẫu là một đoạn mã được biên dịch riêng biệt (ngay cả đối với các tham số mẫu nguyên) mà số nguyên cần phải có khi biên dịch (và phải đảm bảo không bao giờ thay đổi). Đây cũng là lý do tại sao bạn nên sử dụng một số lượng lớn các giá trị duy nhất - bạn có thể nhanh chóng kết thúc bằng một tệp thực thi khổng lồ.

13

Sau đây là từ tiêu chuẩn.

14.3.2.1:

Mẫu đối số cho một tổ chức phi loại, phi mẫu template-tham số sẽ là một trong:

  • một hằng số biểu hiện không thể thiếu trong không thể thiếu hoặc liệt kê kiểu; hoặc
  • tên của thông số mẫu không loại; hoặc
  • địa chỉ của đối tượng hoặc chức năng có liên kết bên ngoài, bao gồm mẫu chức năng và id mẫu chức năng nhưng không bao gồm thành viên lớp không tĩnh, được biểu thị là & id-expression, trong đó & là tùy chọn nếu tên đề cập đến chức năng hoặc mảng, hoặc nếu tham số mẫu tương ứng là một tham chiếu; hoặc
  • con trỏ tới thành viên được thể hiện như mô tả trong 5.3.1.

5.19.1:

Trong một số nơi, C++ đòi hỏi biểu hiện mà đánh giá một hằng số tích phân hoặc liệt kê: như mảng giới hạn (8.3.4, 5.3.4), như trường hợp biểu thức (6.4.2), với độ dài trường bit (9.6), như bộ khởi tạo bảng liệt kê (7.2), là bộ khởi tạo thành viên tĩnh (9.4.2), và là các đối số mẫu không kiểu hoặc liệt kê (14.3).

constant-expression: 
      conditional-expression 

Một liên tục thể hiện không thể thiếu có thể liên quan đến chỉ literals (2.13), điều tra viên, các biến const hay các thành viên dữ liệu tĩnh của loại tách rời hoặc đếm khởi tạo với các biểu thức hằng số (8,5), không loại mẫu tham số của thiếu hoặc liệt kê các loại và biểu thức sizeof. Chữ nổi (2.13.3) chỉ có thể xuất hiện nếu chúng được đúc thành các kiểu tách rời hoặc liệt kê. Chỉ có thể sử dụng loại chuyển đổi cho tích phân hoặc enumera- loại tion.Cụ thể, ngoại trừ trong các biểu thức sizeof, các hàm, đối tượng lớp, con trỏ hoặc tham chiếu sẽ không được sử dụng, và phép gán, tăng, giảm, gọi hàm, hoặc toán tử dấu phẩy sẽ không được sử dụng.

đối với bài trước của bạn Với tôi tin rằng bản chất ở phần "biến const ... khởi với ..." (và tôi không nghĩ rằng khởi tạo bên ngoài đếm).

4

Nó phải là một biểu thức không thể thiếu. Đó là giải thích bằng văn bản tiêu chuẩn tại 5.19:

Một liên tục thể hiện không thể thiếu có thể liên quan đến chỉ literals (2.13), điều tra viên, các biến const hay các thành viên dữ liệu tĩnh của loại tách rời hoặc đếm khởi tạo với các biểu thức hằng số (8,5), không tham số mẫu kiểu của các loại tích phân hoặc kiểu liệt kê và biểu thức sizeof. Chữ nổi (2.13.3) chỉ có thể xuất hiện nếu chúng được đúc thành các kiểu tách rời hoặc liệt kê. Chỉ có thể sử dụng loại chuyển đổi cho các loại tích phân hoặc kiểu liệt kê.

Lưu ý rằng "tích phân" là một thuật ngữ khác cho "số nguyên", nhưng không giống như "int". Ví dụ, char có kiểu số nguyên/tích phân, nhưng không phải là kiểu int. Vì vậy, cụ thể, sau đây được phép

  • 10 or 10L or anything like that
  • enum { THIS, OR, THAT };
  • int const this_one = 10;
  • sizeof(char)
  • tất nhiên, bất kỳ thông số mẫu khác như chi tiết ở trên

Bất kỳ của những người có thể được sử dụng làm đối số mẫu cho tham số có loại tích phân thứ e loại tương ứng. Tuy nhiên, một số chuyển đổi vẫn được áp dụng. Vì vậy, nếu nó muốn một int và bạn vượt qua một char, nó sẽ tự động thúc đẩy char đến int. Tương tự nếu bạn cung cấp một điều tra viên và nó muốn một int.

Vì vậy, bằng những quy tắc này, nếu bạn có

extern const int SomeName; 

Và nó không nhìn thấy một định nghĩa mà khởi rằng thường xuyên với một biểu thức hằng số tích phân, nó không thể được sử dụng như một mẫu đối số. Nhưng nó có thể được sử dụng như một đối số hàm, tất nhiên. Những người không cần phải được biết tại thời gian biên dịch bởi vì những người không phải là một phần của một loại. Thời điểm bạn đặt tên cho một mẫu chuyên môn, các đối số bạn đã sử dụng trở thành một phần của các loại:

MyGreatStack<int, 4> // 4 is now part of the type MyGreatStack<int, 4>! 

Lưu ý rằng có cách khác để vượt qua SomeName như một cuộc tranh cãi. Tuy nhiên, tất cả đều có thể không được chấp nhận bởi tham số mẫu nguyên. Bạn có thể chấp nhận thông số tham chiếu ở trên, ví dụ:

template<const int& V> struct NowItWorks { }; 

Và nó sẽ chấp nhận SomeName ở trên. Bây giờ, thay vì một giá trị, một vị trí cụ thể duy nhất trên toàn bộ chương trình (vì biến có liên kết extern) đã được chọn.

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