2013-06-08 41 views
11

Một chức năng constexpr phải chỉ bao gồm một tuyên bố trở lại và mọi lý luận nên được biết đến tại thời gian biên dịch:constexpr - tại sao chỉ là một tuyên bố trở lại?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 

Tại sao chỉ báo cáo kết quả lợi nhuận? Ý tôi là, tại sao điều này là sai?

// constexpr functions use recursion rather than iteration 
constexpr int factorial(int n) 
{ 
    int a = 222; //another variable 
    return n <= 1 ? 1 : (n * factorial(n-1)); 
} 
+7

Tôi nghi ngờ đó chỉ là phương tiện để đơn giản hóa việc triển khai trình biên dịch. – juanchopanza

+10

Vì tiêu chuẩn nói như vậy. Việc cho phép các hàm tổng quát hơn sẽ làm phức tạp cuộc sống của các trình biên dịch khá nhiều (dù sao, C++ 14 nâng một số hạn chế) –

+3

Bởi vì cho phép các biến có nghĩa là thêm nhiều hạn chế khác (phức tạp hơn). Vì vậy, họ giữ nó đơn giản để giới thiệu của họ. Tuy nhiên, có nhiều cách xung quanh nó (gọi hàm 'constexpr' từ một hàm khác), ví dụ: – Dave

Trả lời

6

Nó đơn giản hóa việc triển khai, như Andy Prowl nói. Điều đó có thể trả lời "Tại sao", nhưng nó không nói nó như thế nào.

Một hàm chỉ có giá trị trả lại và cụ thể hơn là không có biến cục bộ, là tình huống đặc biệt cho trình biên dịch. Hàm này bây giờ bao gồm một biểu thức duy nhất: AST của hàm chỉ cần có một gốc đơn. Việc thiếu các biến có nghĩa là biểu thức này có thể được đánh giá mà không có một máy ảo toàn diện để xử lý nó, thay vào đó một bộ đánh giá biểu thức cây đơn giản có thể được sử dụng. Vì nhiều lý do, trình biên dịch có thể đã có một bộ đánh giá như vậy, hoặc có thể tạo một trình đánh giá tương đối dễ dàng (nó trở thành một sự đơn giản hóa cây).

Chỉ biết rằng constexpr được sử dụng bên trong biểu thức cũng cung cấp một sự đơn giản hóa quan trọng. Điều này đảm bảo rằng mỗi đỉnh trong hàm AST có cùng thuộc tính, ngay cả khi nó là một cuộc gọi hàm. Toàn bộ cơ chế constexpr sau đó là một hình thức tổng quát của const-gấp. Và mặc dù nó không phải luôn luôn được thực hiện ở mức cao này trong trình biên dịch, nó đảm bảo nó có thể được thực hiện mà không có một nỗ lực rất lớn (so với một máy ảo đầy đủ).

Quay lại câu hỏi "tại sao". Hạn chế này chủ yếu là do giới hạn tài nguyên trên các nhà cung cấp. Tính năng này, như được chỉ định, không phải là một nỗ lực rất lớn và do đó các nhà cung cấp thực sự có thể thực hiện nó trong một khoảng thời gian hợp lý. Nếu không có những hạn chế như vậy, đặc biệt cho phép các biến cục bộ, nó làm tăng đáng kể lượng công việc cần thiết. Từ quan điểm của người dùng (chúng tôi, các lập trình viên), các hạn chế là hoàn toàn tùy ý.

+0

Câu trả lời hay. 'constexpr' thực sự yêu cầu trình biên dịch ** giải thích ** nó (thay vì biên dịch), vì vậy phấn đấu cho sự đơn giản là dễ hiểu. Một bổ sung tốt đẹp, mặc dù, sẽ là 'tĩnh if' (hữu ích cho' constexpr', không chỉ cho các mẫu), về tình trạng mà tôi không chắc chắn bây giờ. – eudoxos

+0

Tôi đoán nó cũng vì một lý do khác. Bạn không thể có các vòng lặp vô hạn và các cuộc gọi đệ quy có thể được phát hiện một cách đơn giản bởi forcin một giới hạn đệ quy. Ngoài ra bất kỳ thay đổi nào để constexpr cho phép nhiều thứ hơn cũng ngụ ý những bất biến phức tạp hơn mà người dùng phải tôn trọng để lấy mã biên dịch mà không lang thang tại sao nó không biên dịch. Ngoài ra tôi có nghi ngờ rằng thực sự bạn cũng cần phải "chứng minh" rằng constexpr hoạt động, và prooving nó cho mã tùy ý sẽ được khó khăn hoặc không thể cũng từ quan điểm lý thuyết của xem. – GameDeveloper

13

Tại sao:

constexpr là một khái niệm khá mới và triệt để trong C++ 11 và rất khó để chuyển một tiêu chuẩn ngôn ngữ chính cho một cái gì đó hoàn toàn mới. Quy tắc bảo thủ.

Đối với C++ 1y (hiện được nhắm mục tiêu tại C++ 14), ví dụ của bạn là hợp pháp. Mẹo của thân cây đã được thực hiện dưới cờ -std=c++1y.

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