2016-10-18 31 views
5

Từ Lambda function passed as parameter tôi có thể biên dịch ví dụ:tại sao mã này có C2784 "không thể suy ra mẫu đối số" lỗi

template <class Range> 
Range FindFirstIf(Range, bool(*Function)(typename Range::ConstReference value)); 

struct range { using ConstReference = const float&; }; 

range rng; 
rng = FindFirstIf(rng, [](const float& val) { return (val < 0.0f); }); 

Tất nhiên nó không thể liên kết như FindFirstIf không được thực hiện.

Tuy nhiên, khi tôi đã làm một điều tương tự:

template <class Range, class ValueType> 
Range MyTest(Range, ValueType, bool(*Function)(ValueType value)); 

std::vector <int> vi; 
double d = 0; 
vi =  MyTest(vi, d, [](double val) { return (val < 0.0f); }); 

Nó có lỗi biên dịch:

error C2784: 'Range MyTest(Range,ValueType,bool (__cdecl *)(ValueType))' : could not deduce template argument for 'bool (__cdecl *)(ValueType)' from 'main::'

tại sao như vậy? Tôi nghĩ rằng bằng cách vượt qua d trong, ValueType có thể được suy ra là double?

+0

Không chắc chắn nếu đó là vì các loại '[] (val kép) {return (val <0.0f); } 'không bằng' bool (* Hàm) (giá trị ValueType) '. Tôi đã có một câu hỏi tương tự trước đây, có lẽ bạn có thể kiểm tra nó ra. Ở đây http://stackoverflow.com/questions/24606517/why-cant-i-deduce-template-argument-for-this-function –

+0

Nếu chúng là cùng một vấn đề, điểm mấu chốt là để suy ra 'ValueType', nó yêu cầu 'ValueType' và' bool (* Function) (ValueType value) 'vừa khớp, nhưng kiểu lambda có thể không khớp với' bool (* Function) (ValueType value) '(nghĩa là chúng có thể chuyển đổi, nhưng không bằng nhau) –

+0

'vi = MyTest , double> (vi, d, [] (double val) {return (val <0.0f);});' sẽ hoạt động !! – Praveen

Trả lời

2

Sử dụng này để thay thế (chú ý +):

vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); }); 

Lambda chức năng có thể phân rã chức năng gợi ý trong một số trường hợp, nhưng họ không chức năng gợi ý cho mình.
Nói cách khác, khấu trừ không thành công vì nó dự kiến ​​làm việc trên con trỏ hàm, nhưng lambda không phải là con trỏ hàm, nó có thể được chuyển đổi tất nhiên, nhưng trước hết khấu trừ phải diễn ra, nhưng không thể cho lambda không phải là loại mong đợi, nó có thể phân rã thành nó ... Và cứ thế.
Bằng cách thêm + ở phía trước lambda, bạn buộc chuyển đổi trước khi nó được chuyển đến hàm, do đó MyTest nhận con trỏ hàm thực tế như mong đợi và khấu trừ tiếp tục.

Dưới đây là một tối thiểu, làm việc ví dụ dựa trên mã của bạn:

#include<vector> 

template <class Range, class ValueType> 
Range MyTest(Range, ValueType, bool(*Function)(ValueType value)) {} 

int main() { 
    std::vector <int> vi; 
    double d = 0; 
    vi = MyTest(vi, d, +[](double val) { return (val < 0.0f); }); 
} 
+0

Hi có tài liệu nào về '+' không? Tôi muốn biết thêm, cảm ơn! –

+0

@MarsonMao Bản nháp làm việc, cppreference.com, v.v. Nó là tiêu chuẩn C++. – skypjack

+0

@MarsonMao Hãy xem http://stackoverflow.com/questions/18889028/a-positive-lambda-what-sorcery-is-this?rq=1 –

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