我有一个遗留的非阻塞dequeue API,如下所示:
template <typename T>
bool bad_queue<T>::try_dequeue(T* out);
// Returns 'false' if there was nothing to dequeue.
// Returns 'true' and sets '*out' to the dequeued item otherwise.
我想将bad_queue<T>
包装到我自己的cool_queue<T>
中,该std::optional<T>
从try_dequeue
成员函数返回template <typename T>
class cool_queue
{
private:
bad_queue<T> _q;
public:
std::optional<T> try_dequeue();
};
:
try_dequeue
这是我目前实施template <typename T>
std::optional<T> cool_queue<T>::try_dequeue()
{
T temp;
const auto ok = _q.try_dequeue(&temp);
if(!ok) { return std::nullopt; }
return {std::move(temp)};
}
的方式:
temp
有没有办法避免临时_q.try_dequeue
缓冲区并直接在可选内部构建// PSEUDOCODE
template <typename T>
std::optional<T> cool_queue<T>::try_dequeue()
{
std::optional<T> temp;
const auto ok = _q.try_dequeue(&temp.storage());
if(!ok) { return std::nullopt; }
temp.assume_has_object();
return temp;
}
返回的值?示例:
android.enableAapt2=false
答案 0 :(得分:5)
您无法在可选的via指针中构造值,但您的遗留API无论如何都不允许这样做。您可以改为在可选中默认构造一个值,并将指针传递给:
template <typename T>
std::optional<T> cool_queue<T>::try_dequeue()
{
std::optional<T> temp;
const auto ok = _q.try_dequeue(&temp.emplace());
if (!ok) { temp.reset(); }
return temp;
}
答案 1 :(得分:1)
根据您的描述,遗留try_dequeue
函数似乎没有任何责任初始化为目标对象分配的内存(“... sets'*out
'to ...“),因此需要在遗留(可能是对象分配)调用之前构造目标对象。具体来说,对于目标对象是由std::optional
实例包装的值,如果我们要访问其地址,则实例必须包含(包装)值。
如果std::optional
不包含值,*someOptional
([optional.observe])观察员的要求会隐式指定UB;来自[optional.optional]/1:
在任何给定时间
optional<T>
的任何实例都包含一个 值或不包含值。当一个实例可选 包含一个值,它表示一个T类型的对象,简称为 可选对象的包含值,在存储中分配 可选对象。
您要避免这种情况的唯一方法是更改旧版API。
作为mentioned in a comment by @Casey,您可以对目标对象进行值初始化,并相应地重构cool_queue<T>::try_dequeue()
,例如:
template <typename T>
std::optional<T> cool_queue<T>::try_dequeue()
{
std::optional<T> temp{std::in_place};
return _q.try_dequeue(&*temp) ? temp : std::nullopt;
}