如何正确使用 std::function 作为谓词
How to properly use std::function as a predicate
我想在模板辅助函数中使用 std::function 作为谓词,但出现错误:
main.cpp(15): error C2672: 'Any': no matching overloaded function found
main.cpp(15): error C2784: 'bool Any(const std::vector<T,std::allocator<_Ty>> &,const std::function<bool(const T &)>)': could not deduce template argument for 'const
std::function<bool(const T &)>' from 'main::<lambda_1b47ff228a1af9c86629c77c82b319f9>'
main.cpp(7): note: see declaration of 'Any'
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
int main()
{
auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
if (Any(myList, [](int i) { return i % 5 == 0; }))
{
std::cout << "Bingo!" << std::endl;
}
else
{
std::cout << "Not found :(" << std::endl;
}
return 0;
}
我不明白我做错了什么。
I don't understand what I'm doing wrong.
您正在将 lambda 传递给 Any
,但在 template argument deduction 中不会考虑隐式转换(从 lambda 到 std::function
),这使得 T
无法在第二个函数参数上推导出来。
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
您可以使用 std::type_identity
(C++20 起)从推导中排除第二个参数;那么模板参数 T
将仅根据第一个参数推导出来,然后代码可以正常工作。例如
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const std::type_identity_t<T>&)> predicate)
// ^^^^^^^^^^^^^^^^^^^^^^^
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
如果你不能应用C++20,你可以参考上面的链接页面,它给出了一个可能的实现,实现你自己的并不难type_identity
。如果你不坚持std::function
,你可以为谓词添加另一个模板参数。
template <typename T, typename P>
bool Any(const std::vector<T>& list, P predicate)
{
return std::any_of(list.begin(), list.end(), predicate);
}
或者使其更通用以与其他容器或原始数组一起使用。
template <typename C, typename P>
bool Any(const C& c, P predicate)
{
return std::any_of(std::begin(c), std::end(c), predicate);
}
正确代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
int main()
{
auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))
{
std::cout << "Bingo!" << std::endl;
}
else
{
std::cout << "Not found :(" << std::endl;
}
return 0;
}
if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))
- 您需要指定模板参数(任意)
- 您忘记添加 return 类型的 lambda
我想在模板辅助函数中使用 std::function 作为谓词,但出现错误:
main.cpp(15): error C2672: 'Any': no matching overloaded function found main.cpp(15): error C2784: 'bool Any(const std::vector<T,std::allocator<_Ty>> &,const std::function<bool(const T &)>)': could not deduce template argument for 'const std::function<bool(const T &)>' from 'main::<lambda_1b47ff228a1af9c86629c77c82b319f9>' main.cpp(7): note: see declaration of 'Any'
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
int main()
{
auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
if (Any(myList, [](int i) { return i % 5 == 0; }))
{
std::cout << "Bingo!" << std::endl;
}
else
{
std::cout << "Not found :(" << std::endl;
}
return 0;
}
我不明白我做错了什么。
I don't understand what I'm doing wrong.
您正在将 lambda 传递给 Any
,但在 template argument deduction 中不会考虑隐式转换(从 lambda 到 std::function
),这使得 T
无法在第二个函数参数上推导出来。
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
您可以使用 std::type_identity
(C++20 起)从推导中排除第二个参数;那么模板参数 T
将仅根据第一个参数推导出来,然后代码可以正常工作。例如
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const std::type_identity_t<T>&)> predicate)
// ^^^^^^^^^^^^^^^^^^^^^^^
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
如果你不能应用C++20,你可以参考上面的链接页面,它给出了一个可能的实现,实现你自己的并不难type_identity
。如果你不坚持std::function
,你可以为谓词添加另一个模板参数。
template <typename T, typename P>
bool Any(const std::vector<T>& list, P predicate)
{
return std::any_of(list.begin(), list.end(), predicate);
}
或者使其更通用以与其他容器或原始数组一起使用。
template <typename C, typename P>
bool Any(const C& c, P predicate)
{
return std::any_of(std::begin(c), std::end(c), predicate);
}
正确代码:
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
template <typename T>
bool Any(const std::vector<T>& list, const std::function<bool(const T&)> predicate)
{
return std::any_of(list.begin(), list.end(), [&](const T& t) { return predicate(t); });
}
int main()
{
auto myList = std::vector<int>{ 1, 2, 3, 4, 5 };
if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))
{
std::cout << "Bingo!" << std::endl;
}
else
{
std::cout << "Not found :(" << std::endl;
}
return 0;
}
if (Any<int>(myList, [](int i) -> bool { return i % 5 == 0; }))
- 您需要指定模板参数(任意)
- 您忘记添加 return 类型的 lambda