gpt4 book ai didi

c++ - 将左值传递给右值

转载 作者:可可西里 更新时间:2023-11-01 17:04:10 25 4
gpt4 key购买 nike

我做了一个小的“阻塞队列”类。令我恼火的是,我为传递到 enqueue 成员函数的值创建了冗余代码。

这两个函数做同样的事情(除了右值使用 std::move 将右值移动到实际的队列集合中),除了分别处理左值和右值:

    void enqueue(const T& item)
{
std::unique_lock<std::mutex> lock(m);
this->push(item);
this->data_available = true;
cv.notify_one();
}

void enqueue(T&& item)
{
std::unique_lock<std::mutex> lock(m);
this->push(std::move(item));
this->data_available = true;
cv.notify_one();
}

我的问题是,有没有一种方法可以结合这两个函数,同时又不失去对右值引用的支持。

最佳答案

这是需要完美转发的经典例子。通过模板化函数(成员模板,如果这是一个成员函数)来做到这一点:

template <class U>
void enqueue(U&& item)
{
std::unique_lock<std::mutex> lock(m);
this->push(std::forward<U>(item));
this->data_available = true;
cv.notify_one();
}

解释:如果你传递一个左值TenqueueU会推导出T&,并且forward 会将其作为左值传递,您将获得所需的复制行为。如果将右值 T 传递给 enqueueU 将推断为 T,并且 forward 会将其作为右值传递,您将获得所需的移动行为。

这比“按值传递”方法更有效,因为您永远不会进行不必要的复制或移动。 “按值传递”方法的缺点是该函数接受任何东西,即使它是错误的。在 push 下,您可能会也可能不会收到级联错误。如果这是一个问题,您可以enable_if enqueue 来限制它将实例化的参数。

根据评论更新

根据下面的评论,我的理解是这样的:

#include <queue>
#include <mutex>
#include <condition_variable>

template <class T>
class Mine
: public std::queue<T>
{
std::mutex m;
std::condition_variable cv;
bool data_available = false;
public:

template <class U>
void
enqueue(U&& item)
{
std::unique_lock<std::mutex> lock(m);
this->push(std::forward<U>(item));
this->data_available = true;
cv.notify_one();
}
};

int
main()
{
Mine<int> q;
q.enqueue(1);
}

这一切都很好。但是,如果您尝试将 double 加入队列怎么办:

q.enqueue(1.0);

这仍然有效,因为 double 可以隐式转换为 int。但是,如果您不想让它工作怎么办?然后你可以像这样限制你的enqueue:

template <class U>
typename std::enable_if
<
std::is_same<typename std::decay<U>::type, T>::value
>::type
enqueue(U&& item)
{
std::unique_lock<std::mutex> lock(m);
this->push(std::forward<U>(item));
this->data_available = true;
cv.notify_one();
}

现在:

q.enqueue(1.0);

结果:

test.cpp:31:11: error: no matching member function for call to 'enqueue'
q.enqueue(1.0);
~~^~~~~~~
test.cpp:16:13: note: candidate template ignored: disabled by 'enable_if' [with U = double]
std::is_same<typename std::decay<U>::type, T>::value
^
1 error generated.

但是 q.enqueue(1); 仍然可以正常工作。 IE。限制您的成员模板是您需要做出的设计决定。您希望 enqueue 接受什么 U?没有正确或错误的答案。这是工程判断。还有一些其他测试可能更合适(例如 std::is_convertible、std::is_constructible 等)。也许您的应用程序的正确答案是完全没有约束,如上面的第一个原型(prototype)。

关于c++ - 将左值传递给右值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14667921/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com