C++ 未来处理
C++ Future handling
我正在构建一个 C++ 程序,它使用 API 来尝试获取一些关于包裹跟踪信息的数据,其中一些方法是 returning 未来,如果未来已经实现,我想return它到主程序。考虑以下因素:
std::future<ApiClass> myMethodReturningFuture() {
/* some processing */
std::future<ApiClass> future = api.call();
return future;
}
我的问题是如何正确处理未来(例如,检查它是否包含正确的信息,调用 future.valid() 似乎总是 return 1)。另外,如果未来不是完全有效的,如何从这个函数 return NULL 或 nullptr ?让我们考虑一下这种情况:
std::future<ApiClass> myMethodReturningFuture() {
/* some processing */
try {
std::future<ApiClass> future = api.call();
return future;
} catch (std::exception& e) {
return nullptr // or NULL;
}
}
上面的代码片段无法编译。即使我将函数 return 设为指针,我也会收到有关“使用已删除函数 std::future”的错误消息。像这样:
std::future<ApiClass>* myMethodReturningFuture() {
/* some processing */
try {
std::future<ApiClass>* future = &api.call();
return future;
} catch (std::exception& e) {
return nullptr // or NULL;
}
}
A future
基本上是一些共享状态的包装器。 valid
告诉你 future
是否真的有一些共享状态。
一个 future
如果它是默认构造的,或者如果它的共享状态已经被检索,或者如果它是移动的来源,那么 future
将没有共享状态,所以其他一些 future
现在拥有这个曾经拥有的共享状态。
至少据我了解你在写什么,很有可能你真的只想 return future
原样,并且没有理由检查它之前是否有效你 return 它——特别是,如果你收到一个无效的 future
,相当于你 return 表示默认的“无效未来”-构建了 future
信号“不存在”...通过其 valid
returning false
。换句话说,您可以通过 return 发送与您最初收到的完全相同的类型来表示缺少 future
。
我想你 可以 将“不存在”的信号与 future
分开,如果你真的想的话。例如,您可以这样定义您的函数:
std::optional<std::future<ApiClass>> myMethodReturningFuture() {
在一个理想的1 世界中,每个 class 都完全分解并且只有一个责任,std::future
可能不会存在--你' d 取而代之的是 std::optional<std::shared_state<T>>
之类的东西,而 optional
部分将负责说明它是否存在,而 shared_state
将 仅 处理共享状态。但这不是我们生活的世界,所以 future
的 valid
基本上就像 optional
一样,告诉你共享状态是否存在。
如果你打算这样做,你需要考虑到 future
是可移动但不可复制的事实,所以当你将一个分配给一个变量时,你需要使用 std::move
将其从该变量中取回。例如,这里有一些简单(但完整)的代码来进行检查和 return 一个 std::optional<std::future<T>>
:
#include <optional>
#include <future>
struct ApiClass {
int i;
};
struct Api {
std::future<ApiClass> call() const {
// create and return a (trivial) future.
return std::async(std::launch::async, []{ return ApiClass {1}; });
}
};
std::optional<std::future<ApiClass>> myMethodReturningFuture() {
Api api;
// here we create a `future` object, so it's an lvalue, not an rvalue
std::future<ApiClass> future {api.call()};
// so when we want to create our optional<future>, we need to tell the
// compiler to move instead of copying the object we created:
return future.valid() == 1 ? std::make_optional(std::move(future)) : std::nullopt;
}
1. 嗯,从一个角度来看是理想的。坦率地说,我不确定这种设计在实际使用中是否会如此理想。话又说回来,我不确定“future”在实际使用中是否完全理想。
我正在构建一个 C++ 程序,它使用 API 来尝试获取一些关于包裹跟踪信息的数据,其中一些方法是 returning 未来,如果未来已经实现,我想return它到主程序。考虑以下因素:
std::future<ApiClass> myMethodReturningFuture() {
/* some processing */
std::future<ApiClass> future = api.call();
return future;
}
我的问题是如何正确处理未来(例如,检查它是否包含正确的信息,调用 future.valid() 似乎总是 return 1)。另外,如果未来不是完全有效的,如何从这个函数 return NULL 或 nullptr ?让我们考虑一下这种情况:
std::future<ApiClass> myMethodReturningFuture() {
/* some processing */
try {
std::future<ApiClass> future = api.call();
return future;
} catch (std::exception& e) {
return nullptr // or NULL;
}
}
上面的代码片段无法编译。即使我将函数 return 设为指针,我也会收到有关“使用已删除函数 std::future”的错误消息。像这样:
std::future<ApiClass>* myMethodReturningFuture() {
/* some processing */
try {
std::future<ApiClass>* future = &api.call();
return future;
} catch (std::exception& e) {
return nullptr // or NULL;
}
}
A future
基本上是一些共享状态的包装器。 valid
告诉你 future
是否真的有一些共享状态。
一个 future
如果它是默认构造的,或者如果它的共享状态已经被检索,或者如果它是移动的来源,那么 future
将没有共享状态,所以其他一些 future
现在拥有这个曾经拥有的共享状态。
至少据我了解你在写什么,很有可能你真的只想 return future
原样,并且没有理由检查它之前是否有效你 return 它——特别是,如果你收到一个无效的 future
,相当于你 return 表示默认的“无效未来”-构建了 future
信号“不存在”...通过其 valid
returning false
。换句话说,您可以通过 return 发送与您最初收到的完全相同的类型来表示缺少 future
。
我想你 可以 将“不存在”的信号与 future
分开,如果你真的想的话。例如,您可以这样定义您的函数:
std::optional<std::future<ApiClass>> myMethodReturningFuture() {
在一个理想的1 世界中,每个 class 都完全分解并且只有一个责任,std::future
可能不会存在--你' d 取而代之的是 std::optional<std::shared_state<T>>
之类的东西,而 optional
部分将负责说明它是否存在,而 shared_state
将 仅 处理共享状态。但这不是我们生活的世界,所以 future
的 valid
基本上就像 optional
一样,告诉你共享状态是否存在。
如果你打算这样做,你需要考虑到 future
是可移动但不可复制的事实,所以当你将一个分配给一个变量时,你需要使用 std::move
将其从该变量中取回。例如,这里有一些简单(但完整)的代码来进行检查和 return 一个 std::optional<std::future<T>>
:
#include <optional>
#include <future>
struct ApiClass {
int i;
};
struct Api {
std::future<ApiClass> call() const {
// create and return a (trivial) future.
return std::async(std::launch::async, []{ return ApiClass {1}; });
}
};
std::optional<std::future<ApiClass>> myMethodReturningFuture() {
Api api;
// here we create a `future` object, so it's an lvalue, not an rvalue
std::future<ApiClass> future {api.call()};
// so when we want to create our optional<future>, we need to tell the
// compiler to move instead of copying the object we created:
return future.valid() == 1 ? std::make_optional(std::move(future)) : std::nullopt;
}
1. 嗯,从一个角度来看是理想的。坦率地说,我不确定这种设计在实际使用中是否会如此理想。话又说回来,我不确定“future”在实际使用中是否完全理想。