【发布时间】:2021-06-04 01:08:36
【问题描述】:
我有一些函数可以将一些参数和可调用对象(最后一个参数)作为回调结果。我想将其转换为常规通话。我尝试了这种方法并且它有效,但我必须每次都指定参数类型。
有没有一种解决方案可以帮助我自动推断回调参数类型并将它们转换为函数的返回类型?
#include <functional>
#include <iostream>
void foo1(std::function<void(int)> &&f) {
f(42);
}
void foo1(std::string arg, std::function<void(std::string)> &&f) {
f(std::move(arg));
}
void foo2(std::function<void(float)> &&f) {
f(42.42f);
}
template <typename F>
void foo3(F &&f) {
f(42);
}
template <typename Arg>
auto call(auto &&f) {
Arg res;
f([&res](Arg arg) {
res = std::move(arg);
});
return res;
}
int main() {
std::cout << call<float>([](auto &&callback) { foo2(callback); }) << std::endl;
std::cout << call<int>([](auto &&callback) { foo1(callback); }) << std::endl;
std::cout << call<std::string>([](auto &&callback) { foo1("hello", callback); }) << std::endl;
// should work not only with std::function
std::cout << call<int>([](auto &&callback) { foo3(callback); }) << std::endl;
// is there a way to automatically deduce return type from callback?
// std::cout << call<auto>([](auto &&callback) { foo2(callback); }) << std::endl;
// std::cout << call<auto>([](auto &&callback) { foo3(callback); }) << std::endl;
// // this shouldn't compile, cause of ambiguous call
// std::cout << call<auto>([](auto &&callback) { foo1(callback); }) << std::endl;
}
如果可能,如果回调有多个参数,我还想返回带有结果的元组
void foo4(std::function<void(float, int)> &&f) {
f(42.42f, 42);
}
auto [a, b] = call<auto>([](auto &&callback) { foo4(callback); });
如果能提供任何帮助,我们将不胜感激。
【问题讨论】:
-
在您的示例中,
call始终采用 lambda。将 lambdas 传递给call的解决方案是否足够?还是call需要接受任何可调用的? -
我猜 lambda 就足够了。
-
好吧,如果我能像这样使用就完美了 call(foo1, "arg");但我想它已经太复杂了,如果它完全可以处理重载,我也想知道
-
call<float>([](auto &&callback) { foo2(callback); })可以是call<float>(foo2),从foo2,我们可以知道输入参数(而通用 lambdas 允许任何类型)。 -
从
[](auto){..},你不能推断出任何东西,auto可以是任何东西(即使主体随后会因无效参数而失败)。call(&foo2)很简单,没有重载,不涉及模板,所以我们可以推断出foo2的参数,foo1有重载,所以call(&foo1)是模棱两可的。类似call(&foo3),你想要哪个T?
标签: c++ template-meta-programming c++20 template-argument-deduction