2013-04-08 36 views
22

Khi trả lời this SO question, tôi tìm thấy trong tiêu chuẩn (đã có C++ 03, vẫn còn trong C++ 11) mà bạn chỉ có thể sử dụng địa chỉ làm đối số mẫu không biểu mẫu & id-expression (cộng với một số ngoại lệ).con trỏ làm đối số mẫu không phải kiểu

Nhưng tôi không thể trả lời lý do tại sao trường hợp này xảy ra.

luận

14.3.2 Mẫu phi loại [temp.arg.nontype]

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

[...]

- biểu thức liên tục (5.19) chỉ định địa chỉ của đối tượng có lưu trữ tĩnh> thời lượng và liên kết bên ngoài hoặc bên trong hoặc chức năng có liên kết bên ngoài hoặc bên trong, bao gồm mẫu chức năng và mẫu chức năng -trên nhưng exc luding thành viên lớp không tĩnh, thể hiện (bỏ qua dấu ngoặc đơn) như & id-expression, ngoại trừ & có thể bỏ qua nếu tên đề cập đến hàm hoặc mảng và sẽ bị bỏ qua nếu tham số mẫu tương ứng là tham chiếu; [...]

(n3485, tôi nhấn mạnh)

Ví dụ:

using TFoobar = int (*)(); 
template < TFoobar tp > struct foo_struct{}; 

int foobar() { return 42; } 
constexpr TFoobar pFoobar = &foobar; 

foo_struct < &foobar > o0; // fine 
foo_struct <pFoobar> o1; // ill-formed 

Tôi đoán nó có cái gì để làm với các giai đoạn dịch thuật, cụ thể là trình biên dịch không biết nhiều về địa chỉ. Tuy nhiên, tại sao nó không được phép? Không nên nó có thể cho trình biên dịch sử dụng một cái gì đó tương tự như thay thế vĩ mô để thay thế pFoobar với &foobar?

+1

Câu hỏi hay. –

+1

Tôi đoán đó là vấn đề làm thay đổi bảo thủ.C++ 11 có đầy đủ các cách thực sự nghiêm ngặt đối với ngôn ngữ để thực hiện mọi thứ để làm cho mọi thứ dễ dàng hơn cho các trình biên dịch trình biên dịch. Nó có thể được mở rộng C++ 11 để cho phép ở trên, nhưng đó là một vấn đề cho C + + 14 hoặc hơn thế nữa! – Yakk

+0

[Có đề xuất] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4268.html) để xóa những hạn chế này. – dyp

Trả lời

1

Xem xét các lớp học Foo<&X>Foo<&Y>, cả hai đều có thành viên tĩnh int Bar. Trình liên kết phải có thể biết liệu chương trình của bạn có 1 hoặc 2 đối tượng Bar không. Bây giờ, hãy xem xét mối liên kết cũng là bên có nhiều khả năng chịu trách nhiệm về việc gán giá trị cho &X&Y.

Xem lại tiêu chuẩn. Khi được viết, trình biên dịch không cần phải giao tiếp địa chỉ thực tế tới trình liên kết. Thay vào đó, nó vượt qua id-expression. Các liên kết đã hoàn toàn có khả năng xác định xem hai số của id-expression có giống nhau hay không, thậm chí trước khi gán một địa chỉ số cho chúng.

+1

Tôi biết rằng thay thế có thể được sử dụng thay cho địa chỉ thực tế. Nhưng làm thế nào mà trả lời câu hỏi của tôi tại sao một đối tượng 'constexpr' không thể được sử dụng như một đối số mẫu con trỏ? – dyp

+0

Và, để thêm vào nhận xét DyP, nếu một con trỏ constexpr thành hàm được thực hiện, giá trị của nó có thể được tính và truyền cho trình liên kết (hoặc '& id' hoặc' nullptr') (và nhiều hơn nữa: điều này không mâu thuẫn với câu trả lời của bạn). – Synxis

+0

@Synxis: Không, trình biên dịch không thể tính toán giá trị của một con trỏ (constexpr) để hoạt động, vì trình liên kết sẽ cung cấp cho hàm địa chỉ của nó. – MSalters

0
  1. Nó không thể là biến vì các biến chỉ được đặt khi chạy.
  2. Không thể là constexpr vì không thể biết được giá trị của địa chỉ trong thời gian biên dịch; trong hầu hết các trường hợp, nó sẽ chỉ được sửa sau khi di dời trước khi thực hiện. Nó có thể về mặt lý thuyết là một biểu thức số học (mặc dù nó không được phép trong tiêu chuẩn), nhưng trong trường hợp chung của một địa chỉ của một phần tử mảng, bạn có thể chỉ cần sử dụng &arr[i] thay vì arr + i.
+0

Điều gì không thể là một constexpr? Một địa chỉ hàm được biết tại thời gian biên dịch (bao gồm cả thời gian liên kết). Hơn nữa, việc di chuyển chủ yếu xảy ra đối với các thư viện được chia sẻ, trên các hệ thống hiện đại 'exe' thường không được di dời. – Synxis

+0

Quảng cáo 3: Biểu thức không đổi _is_ được phép trong Chuẩn nếu tôi diễn giải chính xác; nó chỉ bị cấm đối với các hàm (hàm ptrs). Mặc dù tôi có thể thấy lý do tại sao một biểu thức số học không có ý nghĩa nhiều trên một hàm ptr, một biểu thức liên tục đánh giá một hàm ptr có ý nghĩa với tôi, xem ví dụ trong OP (hoặc câu hỏi gốc của Synxis). – dyp

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