2011-01-11 24 views
9

Tôi có một câu hỏi liên quan đến C++ 0x lambdas. Trong mã của tôi, nó sẽ có ích khi biết liệu một kiểu đã cho là kiểu của một biểu thức lambda C++ 0x. Để đưa ra ví dụ:Là một đặc tính C++ is_lambda, hoàn toàn được thực hiện như một thư viện, không thể?

struct foobar 
{ 
    void operator()() 
    { 
    } 
}; 

auto lambda = []{}; 
typedef is_lambda < decltype(lambda) > ::type T; // T would be a true_type 
typedef is_lambda <foobar> ::type T; // T would be a false_type 

Khá dễ dàng để phân biệt biểu thức lambda từ chức năng và loại hàm thành viên. Functors là một vấn đề khác.

Vấn đề tôi thấy ở đây là định nghĩa biểu thức lambda theo chuẩn C++ 0x sắp tới; điều duy nhất phải được xác định là một nhà điều hành cuộc gọi công cộng. Tuy nhiên, điều này cũng đúng đối với một functor; kiểm tra sự hiện diện của toán tử cuộc gọi là không đủ để phân biệt các biểu thức lambda từ các hàm. Hơn nữa, nếu toán tử functor là không phải là, lỗi trình biên dịch sẽ xảy ra, vì SFINAE không áp dụng. Khi nào điều này xảy ra? Toán tử cuộc gọi của functor có thể được tạo khuôn mẫu. Vì vậy, một mã số ví dụ:

typedef decltype(&T::operator()) call_type; 

sẽ làm việc cho cả hai biểu thức lambda và functors với nhà điều hành cuộc gọi không templated, và tạo ra một lỗi biên dịch cho các nhà khai thác cuộc gọi templated.

Tôi tin rằng một đặc điểm is_lambda < > chỉ có thể được tạo bằng các tính năng trình biên dịch nội tại. Bạn có thấy một cách để thực hiện đặc điểm này?

+3

Tôi tự hỏi bạn sẽ sử dụng nó để làm gì? –

+0

Xin lỗi vì trả lời muộn. Có, tôi nghĩ rằng tôi đã thực hiện một lỗi hợp lý. Không có điểm nào trong việc phân biệt các functors thông thường từ lambdas - tôi có thể xem cái sau là cái cũ. Tuy nhiên, cần phải xác định liệu một toán tử cuộc gọi có tồn tại hay không. Đến ngày này, không có giải pháp hoàn toàn chung cho vấn đề này dường như tồn tại. Tôi sẽ sớm giải quyết vấn đề này trong một câu hỏi riêng, cùng với những nỗ lực của tôi. –

+0

@MaximYegorushkin: Đối với một sự khác biệt thúc đẩy: loại của một * đối tượng đóng cửa * nhận dạng duy nhất nó thực hiện. Điều tương tự cũng không nhất thiết là đúng đối với các con trỏ hàm khác hoặc hàm khác như đối tượng. – BCS

Trả lời

8

Kể từ khi đánh giá kết quả lambda trong việc tạo đối tượng đóng cửa, không có bất kỳ sự khác biệt nào ngay khi đối tượng được chuyển đến một hàm hoặc được sao chép. Và, thành thật mà nói, tôi không thể tưởng tượng ra một vấn đề đòi hỏi phải biết liệu một vật thể đến từ lambda.

Chỉnh sửa. Một tiêu chuẩn thậm chí còn có một lưu ý trong 5.1.2/2:

Lưu ý: một đối tượng đóng cửa hoạt động như một đối tượng hàm (20.8) .- cuối note

+0

Tôi tưởng tượng rằng bạn có thể sẵn sàng để biết một loại 'std :: function <...>' có trạng thái hay không.Tuy nhiên, vì các hàm được phép sử dụng các biến 'static' hoặc global, nên chúng sẽ không có nhiều điểm để phân biệt lambdas khỏi hỗn hợp. –

6

Tôi không tin rằng nó có thể được thực hiện-lambdas không thực sự bất cứ điều gì mới ngữ nghĩa, họ chỉ là trình biên dịch tạo functors và do đó sẽ trông giống hệt nhau để functors thường xuyên.

1

Nó có thể xác định một số mã macro xác định nếu một biểu thức là một biểu thức lambda (nhưng điều đó không hữu ích vì nó không cho bạn biết nếu một biểu thức là của một lambda loại).

#include <type_traits> 

template<typename T, typename U> 
struct SameType { 
    static_assert(!std::is_same<T, U>::value, "Must use Lambda"); 
    static T pass(T t) { return t; } 
}; 

template <typename T, typename U> 
T NotLambda(T t, U u) { return SameType<T, U>::pass(t); } 

#define ASSERT_LAMBDA(x) NotLambda(x,x) 

///////////////////////////////////// 

int fn() { return 0; } 

int main() { 
    auto l = []{ return 0; }; 
    return ASSERT_LAMBDA(fn)() +    // << fails 
      ASSERT_LAMBDA(l)() +    // << fails 
      ASSERT_LAMBDA([]{ return 0; })(); // << passes 
} 

Điều này phụ thuộc vào mục 5.1.2.3 xác định rằng mỗi biểu thức lambda có một kiểu riêng biệt (mà tôi nghĩ là thuộc tính duy nhất cho lambdas).

+0

Tôi đã có ý tưởng tương tự. Nếu chỉ có thể thực hiện mà không có macro xấu xí, nhưng trong khi tôi tìm cú pháp của việc sử dụng 'NotLambda' trực tiếp (với biểu thức lambda hai lần), để có thể chấp nhận được, người dùng có thể vô tình cung cấp hai đối tượng hàm riêng biệt. – user2023370

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