通过API输出`st * :: optional <t>`输出`T *`参数

时间:2017-10-27 12:11:09

标签: c++ optional c++17

我有一个遗留的非阻塞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

2 个答案:

答案 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;
}