2015-11-27 28 views
92

Vào cuối buổi nói chuyện của Scott Schurr "Introducing constexpr" at CppCon, anh ta hỏi "Có cách nào để đầu độc một chức năng" không? Sau đó, ông giải thích rằng điều này có thể được thực hiện (mặc dù theo một cách phi tiêu chuẩn) bởi:"ngộ độc một hàm" có nghĩa là gì trong C++?

  1. Đưa một throw trong một chức năng constexpr
  2. Khai báo một chưa được giải quyết extern const char*
  3. Tham chiếu chưa được giải quyết extern trong throw

tôi cảm thấy rằng tôi là một chút ra khỏi sâu của tôi ở đây, nhưng tôi tò mò:

  • "ngộ độc một chức năng" có nghĩa là gì?
  • Ý nghĩa/tính hữu ích của kỹ thuật mà anh phác thảo là gì?
+1

Không bao giờ được nghe về thuật ngữ đó, hãy làm rõ bằng ví dụ ngắn gọn! –

+6

@ πάνταῥεῖ, tôi chỉ làm rõ. Đây là một thuật ngữ 'được biết đến rộng rãi trong các vòng tròn nhỏ' – SergeyA

+4

Anh ấy đang nói về việc đảm bảo rằng mọi lời gọi hàm 'constexpr' được đánh giá tại thời gian biên dịch. –

Trả lời

100

Nói chung, nó đề cập đến việc tạo một hàm không sử dụng được, ví dụ: nếu bạn muốn cấm sử dụng phân bổ động trong một chương trình, bạn có thể "độc" chức năng malloc để nó không thể được sử dụng.

Trong video, anh ấy sử dụng nó theo cách cụ thể hơn, rõ ràng nếu bạn đọc trang trình bày được hiển thị khi nói về ngộ độc chức năng, nói "Một cách để ép buộc chỉ thời gian?"

Vì vậy, anh ấy đang nói về "ngộ độc" chức năng để làm cho nó không thể chạy được trong thời gian chạy, do đó, chỉ chỉ có thể gọi là trong biểu thức không đổi. Kỹ thuật này là có một nhánh trong hàm không bao giờ được thực hiện khi được gọi trong ngữ cảnh biên dịch, và để làm cho nhánh đó chứa một cái gì đó sẽ gây ra lỗi.

Một biểu thức throw được cho phép trong hàm constexpr, miễn là nó không bao giờ đạt được trong các lần gọi hàm biên dịch của hàm (vì bạn không thể ném ngoại lệ vào thời gian biên dịch. cấp phát bộ nhớ). Vì vậy, một biểu thức ném đề cập đến một biểu tượng không xác định sẽ không được sử dụng trong các lời gọi thời gian biên dịch (vì điều đó sẽ không biên dịch được) và không thể được sử dụng trong thời gian chạy, vì biểu tượng không xác định gây ra lỗi liên kết.

Bởi vì ký hiệu không xác định không được sử dụng trong các lần biên dịch hàm, trong thực tế trình biên dịch sẽ không tạo tham chiếu đến ký hiệu, vì vậy không sao cho nó không được xác định.

Điều đó có hữu ích không? Anh ấy đang trình bày cách để làm điều đó, không nhất thiết phải nói đó là ý tưởng hay hoặc hữu ích rộng rãi. Nếu bạn có nhu cầu làm điều đó vì lý do nào đó thì kỹ thuật của anh ấy có thể giải quyết vấn đề của bạn. Nếu bạn không có nhu cầu về nó, bạn không cần phải lo lắng về nó.

Một lý do khiến có thể hữu ích là khi phiên bản biên dịch của một số thao tác không hiệu quả như nó có thể.Có những hạn chế về loại biểu thức được cho phép trong một hàm constexpr (đặc biệt là trong C++ 11, một số hạn chế đã bị loại bỏ trong C++ 14). Vì vậy, bạn có thể có hai phiên bản của một hàm để thực hiện phép tính, một hàm tối ưu, nhưng sử dụng các biểu thức không được phép trong hàm constexpr và hàm đó là hàm constexpr hợp lệ, nhưng sẽ hoạt động kém nếu được gọi là run- thời gian. Bạn có thể đầu độc một sub-tối ưu hóa để đảm bảo nó không bao giờ được sử dụng cho các cuộc gọi thời gian chạy, đảm bảo các phiên bản hiệu quả hơn (không constexpr) được sử dụng cho các cuộc gọi thời gian chạy.

N.B. Hiệu năng của hàm constexpr được sử dụng trong thời gian biên dịch không thực sự quan trọng, bởi vì nó không có thời gian chạy trên không. Nó có thể làm chậm quá trình biên dịch của bạn bằng cách làm cho trình biên dịch làm việc thêm, nhưng nó sẽ không có bất kỳ chi phí hiệu năng thời gian chạy nào.

+1

Tôi đã đọc văn bản của trang trình bày nhưng tôi không thấy kết nối với cụm từ mà anh ấy đang sử dụng. Rõ ràng bây giờ bạn đã giải thích nó, nhưng tôi không thấy nó vào thời điểm đó. Cảm ơn rất nhiều vì câu trả lời tuyệt vời này - Tôi chỉ thích trang web này. –

+0

@PravasiMeet, đặt câu hỏi của riêng bạn, không chiếm đoạt các nhận xét về câu hỏi của người khác về điều gì đó khác biệt. Một giải pháp đơn giản là xác định nó như đã xóa trong mọi đơn vị dịch, hoặc thay thế nó bằng định nghĩa của riêng bạn để tham khảo một biểu tượng không xác định. –

18

'Ngộ độc' một số nhận dạng có nghĩa là bất kỳ tham chiếu nào đến số nhận dạng sau khi 'ngộ độc' là lỗi trình biên dịch cứng. Kỹ thuật này có thể được sử dụng, ví dụ, để không dùng nữa (chức năng IS không được chấp nhận, không bao giờ sử dụng nó!).

Trong GCC theo truyền thống, có một pragma cho điều này: #pragma GCC poison.

+0

Có, nhưng không hoàn toàn theo ý nghĩa được sử dụng trong cuộc nói chuyện đó. –

+0

@ T.C., Ok, tôi có lẽ nên xem nó trước khi trả lời :) – SergeyA

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