問題描述
我正在學習 C++,我正在嘗試實現一個二分查找函數,該函數查找謂詞所包含的第一個元素.該函數的第一個參數是一個向量,第二個參數是一個計算給定元素謂詞的函數.二分查找函數如下所示:
I'm learning C++, and I'm trying to implement a binary search function that finds the first element for which a predicate holds. The function's first argument is a vector and the second argument is a function that evaluates the predicate for a given element. The binary search function looks like this:
template <typename T> int binsearch(const std::vector<T> &ts, bool (*predicate)(T)) {
...
}
如果這樣使用,它會按預期工作:
This works as expected if used like this:
bool gte(int x) {
return x >= 5;
}
int main(int argc, char** argv) {
std::vector<int> a = {1, 2, 3};
binsearch(a, gte);
return 0;
}
但是如果我使用 lambda 函數作為謂詞,我會得到一個編譯器錯誤:
But if I use a lambda function as a predicate, I get a compiler error:
search-for-a-range.cpp:20:5: error: no matching function for call to 'binsearch'
binsearch(a, [](int e) -> bool { return e >= 5; });
^~~~~~~~~
search-for-a-range.cpp:6:27: note: candidate template ignored: could not match 'bool (*)(T)' against '(lambda at
search-for-a-range.cpp:20:18)'
template <typename T> int binsearch(const std::vector<T> &ts,
^
1 error generated.
以上錯誤是由
binsearch(a, [](int e) -> bool { return e >= 5; });
怎么了?為什么編譯器不相信我的 lambda 有正確的類型?
What's wrong? Why is the compiler not convinced that my lambda has the right type?
推薦答案
你的函數 binsearch
接受一個函數指針作為參數.lambda 和函數指針是不同的類型:可以將 lambda 視為實現 operator()
的結構體實例.
Your function binsearch
takes a function pointer as argument. A lambda and a function pointer are different types: a lambda may be considered as an instance of a struct implementing operator()
.
請注意,無狀態 lambda(不捕獲任何變量的 lambda)可隱式轉換為函數指針.由于模板替換,這里隱式轉換不起作用:
Note that stateless lambdas (lambdas that don't capture any variable) are implicitly convertible to function pointer. Here the implicit conversion doesn't work because of template substitution:
#include <iostream>
template <typename T>
void call_predicate(const T& v, void (*predicate)(T)) {
std::cout << "template" << std::endl;
predicate(v);
}
void call_predicate(const int& v, void (*predicate)(int)) {
std::cout << "overload" << std::endl;
predicate(v);
}
void foo(double v) {
std::cout << v << std::endl;
}
int main() {
// compiles and calls template function
call_predicate(42.0, foo);
// compiles and calls overload with implicit conversion
call_predicate(42, [](int v){std::cout << v << std::endl;});
// doesn't compile because template substitution fails
//call_predicate(42.0, [](double v){std::cout << v << std::endl;});
// compiles and calls template function through explicit instantiation
call_predicate<double>(42.0, [](double v){std::cout << v << std::endl;});
}
<小時>
你應該讓你的函數 binsearch
更通用,比如:
template <typename T, typename Predicate>
T binsearch(const std::vector<T> &ts, Predicate p) {
// usage
for(auto& t : ts)
{
if(p(t)) return t;
}
// default value if p always returned false
return T{};
}
從標準算法庫中汲取靈感.
這篇關于將 lambda 傳遞給函數模板的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!