2016-09-30 14 views
5

Biểu thức lambda không được phép trong ngữ cảnh không được đánh giá (ví dụ: trong decltype) và không thể là biểu thức liên tục cho đến gần đây. Do đó không có cách nào để sử dụng chúng trong các đối số mẫu.Đã đánh giá lambex constexpr trong đối số mẫu không loại

Trong C++ 17, tuy nhiên, hàm lambdas biểu thức liên tục sẽ là có thể. Điều này vẫn không cho phép sử dụng chúng trong các đối số mẫu nói chung.

Tuy nhiên đặc biệt cho phi kiểu mẫu đối số không đổi biểu thức biểu thức lambda có thể được sử dụng trong một bối cảnh được đánh giá, ví dụ:

template<int N> struct S { constexpr static int value = N; }; 

int main() { 
    int N = S<[]()constexpr{return 42;}()>::value; 
} 

Đó vẫn không hoạt động mặc dù, bởi vì biểu thức lambda là không được phép một cách rõ ràng trong mẫu đối số cho dù loại hoặc không nhập.

Câu hỏi của tôi là lý do đằng sau việc không cho phép cấu trúc ở trên. Tôi có thể hiểu rằng các kiểu lambdas trong chữ ký chức năng có thể có vấn đề, nhưng ở đây kiểu đóng của chính nó là không liên quan, chỉ có giá trị trả về (hằng số biên dịch) được sử dụng.

Tôi nghi ngờ rằng tất cả các câu lệnh trong phần lambda sẽ trở thành một phần của biểu thức đối số mẫu và do đó SFINAE sẽ cần phải được áp dụng nếu bất kỳ câu lệnh nào trong cơ thể bị hình thành không đúng lúc thay thế. Có lẽ đó sẽ yêu cầu công việc đáng kể từ các nhà phát triển trình biên dịch.

Nhưng đó thực sự là động lực của tôi. Nếu có thể sử dụng cấu trúc ở trên thì SFINAE có thể được sử dụng không chỉ với các biểu thức liên tục, mà còn các câu lệnh khác hợp lệ trong các hàm constexpr (ví dụ: khai báo kiểu chữ).

Bên cạnh tác động đối với người viết trình biên dịch, có bất kỳ vấn đề nào mà điều này có thể gây ra hay không, ví dụ: sự mơ hồ, mâu thuẫn hoặc biến chứng trong tiêu chuẩn?

+4

Tôi nghĩ rằng bạn đã trả lời câu hỏi của riêng bạn. – Barry

+0

Vâng, +1 @Barry và đây thực sự là một câu hỏi thú vị. – skypjack

+0

@Barry Tôi đã sửa đổi một chút câu hỏi của mình. Tôi hy vọng cho một số xác nhận rằng đây thực sự là lý do chính (duy nhất), có thể một số tham chiếu đến một bài báo/thảo luận của ủy ban đề cập đến lý do. – user4407569

Trả lời

2

Đó là khá có chủ ý rằng lambdas không xuất hiện trong bối cảnh không được đánh giá. Thực tế là lambdas luôn có các loại duy nhất dẫn đến tất cả các loại vấn đề.

Dưới đây là một vài ví dụ từ một comp.lang.c++ discussion, từ Daniel Krugler:

Có thực sự sẽ tồn tại một số lượng lớn các trường hợp sử dụng cho phép lambda biểu thức, nó có lẽ sẽ vô cùng mở rộng trường hợp sfinae thể (để bao gồm mã hoàn chỉnh "hộp cát"). Lý do tại sao họ trở thành bị loại trừ là do sự mở rộng nghiêm trọng của trường hợp sfinae này (bạn đã mở một hộp Pandora cho trình biên dịch) và thực tế là nó có thể dẫn đến các sự cố về các ví dụ khác như của bạn, ví dụ:

template<typename T, typename U> 
void g(T, U, decltype([](T x, T y) { return x + y; }) func); 

là vô ích, bởi vì tất cả các biểu thức lambda tạo ra một loại độc đáo, vì vậy cái gì đó như

g(1, 2, [](int x, int y) { return x + y; }); 

không thực sự làm việc, bởi vì các loại của lambda được sử dụng trong các tham số khác loại lambda trong cuộc gọi đến g.

Cuối cùng, nó cũng gây ra các vấn đề mang tên. Ví dụ.khi bạn có

template<typename T> 
void f(T, A<sizeof([](T x, T y) { return x + y; })> * = 0); 

trong một đơn vị dịch nhưng

template<typename T> 
void f(T, A<sizeof([](T x, T y) { return x - y; })> * = 0); 

trong một đơn vị dịch thuật. Giả sử bây giờ bạn tạo nhanh f<int> từ cả hai đơn vị dịch. Hai hàm này có các chữ ký khác nhau, vì vậy chúng phải tạo ra các mẫu có dạng khác nhau . Cách duy nhất để giữ chúng riêng biệt là mangle các cơ quan của lambdas. Điều đó, đến lượt nó, có nghĩa là các nhà văn biên dịch có để đưa ra các quy tắc mangling tên cho mọi loại tuyên bố bằng ngôn ngữ . Mặc dù về mặt kỹ thuật, điều này được coi là một đặc điểm kỹ thuật của và gánh nặng triển khai.

Đó là toàn bộ các vấn đề. Đặc biệt là cho rằng motiviation bạn viết:

int N = S<[]()constexpr{return 42;}()>::value; 

có thể dễ dàng giải quyết bằng cách thay vì viết:

constexpr auto f = []() constexpr { return 42; } 
int N = S<f()>::value; 
+0

Tất nhiên bây giờ mà tôi đăng này, tôi cũng tìm thấy [này Q/A] (http://stackoverflow.com/q/22232164/2069064). – Barry

+0

Tôi hoàn toàn không hiểu vấn đề với các đối số mẫu là gì: chúng không phải là một phần của chữ ký, và tại sao SFINAE nên áp dụng cho cơ thể lambda? – dyp

+0

@dyp SFINAE là thứ yếu để thực sự có lambdas ở nơi đầu tiên. Tôi không nghĩ rằng vấn đề. – Barry

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