从模板 Callable 生成承诺
Generate a promise from a template Callable
我正在尝试从接受 Callable 类型的模板函数创建承诺。但我不确定该怎么做。我尝试使用 std::invoke_result_t
,但是这需要参数来知道结果类型,这是我在构建承诺时不知道的。
有什么方法可以推断出 return 类型?我想这在通用 lambda 的情况下可能是不可能的,但是在非通用 lambda 情况下有什么用吗?
template <typename Callable, typename Promise>
class Job {
public:
Job(Callable&& c, Promise&& p)
: callable(std::move(c))
, promise(std::move(p))
{}
auto getFuture() {
return /* a std::shared_future */;
}
template<typename... Args>
void call(Args&&... args) {
promise.set_value(std::invoke(callable, args...));
}
private:
Callable callable;
Promise promise;
};
template<typename Callable>
decltype(auto) makeJob(Callable&& c) {
std::promise</* some type */> promise = /* something */;
return Job(std::forward<Callable>(c), std::move(promise));
}
int main() {
f1 = [](int arg){return arg;};
auto job = makeJob(std::move(f1));
auto future = job.getFuture();
job.call(1);
std::cout << future.get() << '\n';
}
Any way in which I can deduce the return type? I guess it may be impossible in the case of a generic lambda, but does anything work on non generic lambda cases?
您标记了 C++17,所以...std::function
推导指南是您的朋友。
您可以使用
检测可调用对象的 return 类型
typename decltype(std::function{c})::result_type;
所以你的makeJob()
函数可以写成
template <typename Callable>
auto makeJob (Callable && c)
{
using retT = typename decltype(std::function{c})::result_type;
return Job{std::forward<Callable>(c), std::promise<retT>{}};
}
Job
class.
中相同
显然这是可行的,因为 f1
auto f1 = [](int arg){return arg;};
有一个不依赖于参数的 return 类型;使用通用 lambda
// ..........vvvv
auto f1 = [](auto arg){return arg;};
这个解决方案不再有效,我不认为你可以在不知道参数类型的情况下编写一些东西来获取 return 类型。
下面是一个完整的编译示例
#include <future>
#include <memory>
#include <iostream>
#include <functional>
template <typename C, typename P>
class Job
{
public:
using retT
= typename decltype(std::function{std::declval<C>()})::result_type;
Job (C && c, P && p) : callable{std::move(c)}, promise{std::move(p)}
{ }
auto getFuture ()
{ return std::shared_future<retT>{ promise.get_future() }; }
template <typename ... Args>
void call (Args && ... args)
{ promise.set_value(std::invoke(callable, args...)); }
private:
C callable;
P promise;
};
template <typename Callable>
auto makeJob (Callable && c)
{
using retT
= typename decltype(std::function{c})::result_type;
return Job{std::forward<Callable>(c), std::promise<retT>{}};
}
int main ()
{
auto f1 = [](int arg){return arg;};
auto job = makeJob(std::move(f1));
auto future = job.getFuture();
job.call(42);
std::cout << future.get() << '\n';
}
我正在尝试从接受 Callable 类型的模板函数创建承诺。但我不确定该怎么做。我尝试使用 std::invoke_result_t
,但是这需要参数来知道结果类型,这是我在构建承诺时不知道的。
有什么方法可以推断出 return 类型?我想这在通用 lambda 的情况下可能是不可能的,但是在非通用 lambda 情况下有什么用吗?
template <typename Callable, typename Promise>
class Job {
public:
Job(Callable&& c, Promise&& p)
: callable(std::move(c))
, promise(std::move(p))
{}
auto getFuture() {
return /* a std::shared_future */;
}
template<typename... Args>
void call(Args&&... args) {
promise.set_value(std::invoke(callable, args...));
}
private:
Callable callable;
Promise promise;
};
template<typename Callable>
decltype(auto) makeJob(Callable&& c) {
std::promise</* some type */> promise = /* something */;
return Job(std::forward<Callable>(c), std::move(promise));
}
int main() {
f1 = [](int arg){return arg;};
auto job = makeJob(std::move(f1));
auto future = job.getFuture();
job.call(1);
std::cout << future.get() << '\n';
}
Any way in which I can deduce the return type? I guess it may be impossible in the case of a generic lambda, but does anything work on non generic lambda cases?
您标记了 C++17,所以...std::function
推导指南是您的朋友。
您可以使用
检测可调用对象的 return 类型typename decltype(std::function{c})::result_type;
所以你的makeJob()
函数可以写成
template <typename Callable>
auto makeJob (Callable && c)
{
using retT = typename decltype(std::function{c})::result_type;
return Job{std::forward<Callable>(c), std::promise<retT>{}};
}
Job
class.
显然这是可行的,因为 f1
auto f1 = [](int arg){return arg;};
有一个不依赖于参数的 return 类型;使用通用 lambda
// ..........vvvv
auto f1 = [](auto arg){return arg;};
这个解决方案不再有效,我不认为你可以在不知道参数类型的情况下编写一些东西来获取 return 类型。
下面是一个完整的编译示例
#include <future>
#include <memory>
#include <iostream>
#include <functional>
template <typename C, typename P>
class Job
{
public:
using retT
= typename decltype(std::function{std::declval<C>()})::result_type;
Job (C && c, P && p) : callable{std::move(c)}, promise{std::move(p)}
{ }
auto getFuture ()
{ return std::shared_future<retT>{ promise.get_future() }; }
template <typename ... Args>
void call (Args && ... args)
{ promise.set_value(std::invoke(callable, args...)); }
private:
C callable;
P promise;
};
template <typename Callable>
auto makeJob (Callable && c)
{
using retT
= typename decltype(std::function{c})::result_type;
return Job{std::forward<Callable>(c), std::promise<retT>{}};
}
int main ()
{
auto f1 = [](int arg){return arg;};
auto job = makeJob(std::move(f1));
auto future = job.getFuture();
job.call(42);
std::cout << future.get() << '\n';
}