提问人:Jepessen 提问时间:10/5/2023 更新时间:10/6/2023 访问量:88
使用函数时避免使用指定模板参数
Avoid to specity template argument when using a function
问:
我想编写一个将 a 作为参数的模板函数,如下所示:std::function
template<typename T>
void registerDelegate(std::function<void(const T&)> d) {
d(T{});
}
当我想使用它时,我需要以明确的方式编写模板参数:T
auto d = [](const std::string& message) { int i = 0; };
registerDelegate<std::string>(d);
这很烦人,因为我已经在 lambda 中定义了它。有没有办法避免它,简单地写:
registerDelegate(d);
当我想使用该功能时,同时始终知道 T 是什么?
答:
2赞
YSC
10/5/2023
#1
您可以利用 的扣除指南:std::function
template<class Functor>
void registerDelegate(Functor&& functor)
{
std::function f = functor;
(void) f;
}
如果需要访问参数类型:
template<class Functor>
auto to_function(Functor&& functor)
{
std::function f = functor;
return f;
}
template<class Arg>
void registerDelegate(std::function<void(const Arg&)> d) {
d(Arg{});
}
auto d = [](std::string const&){};
registerDelegate(to_function(d));
1赞
Jan Schultke
10/5/2023
#2
问题在于,在模板参数推导过程中不考虑隐式转换。如果你想推导出 ,你需要一个 ,而不仅仅是可转换为 的东西。T
registerDelegate
std::function
std::function
在 C++17 中,这可以通过使用类模板参数推导和 std::function
推导指南轻松解决。
auto d = [](std::string const&){};
registerDelegate(std::function{d});
3赞
Ted Lyngmo
10/5/2023
#3
您可以将提供给的任何函子转发给 lambda(或函数模板),以 a 来推断。registerDelegate
std::function<void(const T&>
T
template <class F>
void registerDelegate(F&& d) {
[]<class T>(std::function<void(const T&)> del) {
del(T{});
}(std::function(std::forward<F>(d))); // use std::function's deduction guides
}
您可以为尚未包装在 中的函子/函数添加函数模板,而不是更改当前已匹配的函数模板:std::function<void(const T&)>
std::function
template<class F>
decltype(auto) registerDelegate(F&& func) {
// call your already existing function:
return registerDelegate(std::function(std::forward<F>(func)));
// ^ use std::function's deduction guides
}
评论
0赞
Ted Lyngmo
10/5/2023
@Jepessen 这是一篇相当宽松的文章。:)你的意思是你的函数仍然需要一个,但你希望它与无法推断类型的东西相匹配吗?std::function<void(const T&)>
std::function
0赞
Jepessen
10/6/2023
基本上是的。我们正在使用受我之前评论中链接的文章启发的自定义委托,因为它通常比 .因此,我们在代码中使用此类而不是 std::function。我在示例中使用它只是为了了解我需要什么,但现在我认为我必须编写我的委托演绎指南......std::function
1赞
Ted Lyngmo
10/6/2023
@Jepessen我明白了。是的,要使相同的解决方案适用于非类型,它需要类似的演绎指南。另一个说明:正如我在答案中暗示的那样,您也可以将函数转发到您现有的函数模板。我把它添加到答案中,以使其更清楚。std::function
F
std::function<void(const T&>
评论
registerDelegate(std::function(d));
std::function d = [](std::string) {...}; registerDelegate(d);
registerDelegate
std::function<...>
std::function<void(std::string)>
T