[英]error C2783: '_Ty &&std::forward(remove_reference<_Ty>::type &&) throw()' : could not deduce template argument for '_Ty'
I have a templated implementation of a concurrent queue that has a push function that looks like: 我有一个带有push函数的并发队列的模板化实现,如下所示:
template <typename T>
class concurrent_queue
{
public:
// other code...
void push(const T& item)
{
std::unique_lock<std::mutex> mlock(mutex);
queue.push_back(std::forward(item));
mlock.unlock();
notEmpty.notify_one();
}
private:
std::deque<T> queue;
std::mutex mutex;
// other stuff...
};
Later on, I instantiate it and use it like so: 稍后,我实例化它并像这样使用它:
concurrent_queue<c2Type> m_queue; // c2 type is some struct declared previously
and then I try to push items on the queue and I get the afore mentioned compiler error: 然后我尝试推送队列上的项目,我得到上面提到的编译器错误:
c2Type c2message;
// fill in the message struct...
m_queue.push(c2message);
I've sucessfully used the queue before as part of a thread pool implementation where it stored std::function
objects. 我之前成功地使用了队列作为线程池实现的一部分,它存储了std::function
对象。 I don't understand why it can't deduce the type in this case. 我不明白为什么在这种情况下不能推断出类型。 Any thoughts? 有什么想法吗?
Value categories like "lvalue" and "rvalue" are properties of expressions. 像“左值”和“右值”这样的值类别是表达式的属性。 Expressions that name variables are always lvalue-expressions, even if they name a variable that has the type rvalue reference to some_type
. 名称变量的表达式总是lvalue表达式,即使它们命名的变量具有对some_type
的类型rvalue引用 。
We use lvalue-reference and rvalue-references to bind different categories of expressions: Per convention, we treat lvalue-references as being bound to lvalues , and rvalue-references as being bound to rvalues . 我们使用lvalue-reference和rvalue-references来绑定不同类别的表达式:按照惯例,我们将lvalue-references视为绑定到lvalues ,并将rvalue-references视为绑定到rvalues 。
std::forward
is intended to restore the value category of what we assume a reference refers to. std::forward
旨在恢复我们假设引用所引用的值类别。 For example: 例如:
int i = 42;
int& l = i;
int&& r = 21;
l // this expression is an lvalue-expression
r // this expression is an lvalue-expression, too (!)
std::forward<int& >(l) // this function-call expression is an lvalue-expression
std::forward<int&&>(r) // this function-call expression is an rvalue-expression
std::forward
, being "an ordinary function", cannot restore the value category merely by using the argument. std::forward
,是“普通函数”,不能仅仅通过使用参数来恢复值类别。 Both arguments are lvalue-expressions. 两个参数都是左值表达式。 You have to specify which value category you want to restore by manually supplying the template-argument. 您必须通过手动提供template-argument来指定要还原的值类别。
This makes only sense if we have a reference where we don't know a priori whether it's an rvalue-reference or an lvalue-reference. 只有当我们有一个我们不知道先验的参考是否是右值参考或左值参考时,这才有意义。 That is the case when writing a function that uses perfect forwarding with forwarding references . 编写使用带转发引用的 完美转发的函数时就是这种情况。
By the way, we want to restore the value category to allow another function to move from the argument we have received. 顺便说一句,我们想要恢复值类别,以允许另一个函数从我们收到的参数移开。 If we receive an rvalue argument, we want to pass on an rvalue, to allow the called function to move. 如果我们收到一个rvalue参数,我们想传递一个rvalue,以允许被调用的函数移动。
For a function like the one in the OP: 对于像OP中那样的函数:
void push(const T& item)
We know that item
has the type lvalue reference to const T
. 我们知道, item
的类型是左值参考const T
。 Therefore, we don't need std::forward
: 因此,我们不需要std::forward
:
void push(const T& item) {
// ...
queue.push_back(item); // pass the lvalue argument as an lvalue
// ...
}
If we add another overload: 如果我们添加另一个重载:
void push(T&& item)
we still don't need std::forward
, since the type of that parameter item
is always rvalue-reference to T
(assuming T
is not a reference type) : 我们仍然不需要std::forward
,因为该参数item
的类型总是rvalue-reference to T
(假设T
不是引用类型) :
void push(T&& item) {
// ...
queue.push_back(std::move(item)); // pass the rvalue argument as an rvalue
// ...
}
Only if we have something like 只有我们有类似的东西
template<typename U>
void push(forwarding_reference<U> item)
where forwarding_reference<U>
can be either an lvalue-reference or an rvalue-reference , then we need std::forward
: 其中forwarding_reference<U>
可以是左值引用或右值引用 ,那么我们需要std::forward
:
template<typename U>
void push(forwarding_reference<U> item) // not C++, read on
{
// ...
queue.push_back(std::forward<U>(item)); // pass lvalue arguments as lvalues
// and rvalue arguments as rvalues
// ...
}
Due to implementation details, we must write the above as: 由于实施细节,我们必须将上述内容写成:
template<typename U>
void push(U&& item) {
// ...
queue.push_back(std::forward<U>(item)); // pass lvalue arguments as lvalues
// and rvalue arguments as rvalues
// ...
}
Note that the above U&& item
is not an rvalue-reference, but a forwarding reference. 请注意,上面的U&& item
不是 rvalue-reference,而是转发引用。 To get a forwarding reference, you need to have a function template with some template type parameter X
and a function parameter of the form X&& x
. 要获得转发引用,您需要一个带有一些模板类型参数X
的函数模板和一个X&& x
形式的函数参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.