将 lambda 函数传递给模板方法
我有以下模板化方法:
auto clusters = std::vector<std::pair<std::vector<long>, math::Vector3f>>
template<class T>
void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
{
}
我有一个看起来像的函数
auto comp1 = [&](
const std::pair<std::vector<long>, math::Vector3f>& n1,
const std::pair<std::vector<long>, math::Vector3f>& n2
) -> int {
return 0;
};
math::eraserFunction(clusters, comp1);
但是,我收到一个语法错误:
116 | void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
| ^~~~~~~~~~~~~~
core.hpp:116:6: note: template argument deduction/substitution failed:
geom.cpp:593:23: note: 'math::method(const at::Tensor&, const at::Tensor&, int, float, int, int, float)::<lambda(const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&, const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&)>' is not derived from 'std::function<int(const T&, const T&)>'
593 | math::eraserFunction(clusters, comp1);
I have the following templated method:
auto clusters = std::vector<std::pair<std::vector<long>, math::Vector3f>>
template<class T>
void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
{
}
And I have a function that looks like
auto comp1 = [&](
const std::pair<std::vector<long>, math::Vector3f>& n1,
const std::pair<std::vector<long>, math::Vector3f>& n2
) -> int {
return 0;
};
math::eraserFunction(clusters, comp1);
However, I get a syntax error saying:
116 | void eraserFunction(std::vector<T>& array, std::function<int(const T&, const T&)> func)
| ^~~~~~~~~~~~~~
core.hpp:116:6: note: template argument deduction/substitution failed:
geom.cpp:593:23: note: 'math::method(const at::Tensor&, const at::Tensor&, int, float, int, int, float)::<lambda(const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&, const std::pair<std::vector<long int>, Eigen::Matrix<float, 3, 1> >&)>' is not derived from 'std::function<int(const T&, const T&)>'
593 | math::eraserFunction(clusters, comp1);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
函数调用尝试从第一个和第二个函数参数中推导出
T
。它将从第一个参数正确推导
T
,但无法从第二个参数推导它,因为第二个函数参数是 lambda 类型,而不是std::function
类型。如果无法从推导上下文的所有参数进行推导,则推导失败。
您实际上不需要在这里从第二个参数/参数进行推导,因为
T
应该完全由第一个参数确定。因此,您可以将第二个参数设置为非推导上下文,例如使用std::type_identity
:这需要 C++20,但如果您的能力有限,也可以在用户代码中轻松实现到 C++11:
然后
std::identity_type_t
是std::identity_type::type
的类型别名。留给范围解析运算符::
的所有内容都是非推导的上下文,这就是它起作用的原因。如果您没有任何特殊原因在这里使用
std::function
,您也可以将任何可调用类型作为第二个模板参数:这可以使用 lambda、函数指针、
std::function
等作为参数。如果参数不可使用预期类型调用,则在包含调用的函数体实例化时将导致错误。您可以使用 SFINAE 或自 C++20 起的类型约束来在重载决策时强制执行此操作。The function call tries to deduce
T
from both the first and second function parameter.It will correctly deduce
T
from the first parameter, but fail to deduce it from the second parameter, because the second function argument is a lambda type, not astd::function
type.If deduction isn't possible from all parameters that are deduced context, deduction fails.
You don't really need deduction from the second parameter/argument here, since
T
should be fully determined by the first argument. So you can make the second parameter a non-deduced context, for example by usingstd::type_identity
:This requires C++20, but can be implemented easily in user code as well if you are limited to C++11:
and then
std::identity_type_t<T>
is a type alias forstd::identity_type<T>::type
. Everything left to the scope resolution operator::
is a non-deduced context, which is why that works.If you don't have any particular reason to use
std::function
here, you can also just take any callable type as second template argument:This can be called with a lambda, function pointer,
std::function
, etc. as argument. If the argument is not callable with the expected types, it will cause an error on instantiation of the function body containing the call. You can use SFINAE or since C++20 a type constraint to enforce this already at overload resolution time.