在这些直接在函数中使用参数的情况下,我是否需要完善前向参数?
Do I need to perfect forward arguments in these cases where the arguments are used directly in the function?
我心想,我的函数中不需要 std::forward<T>(arg);
,因为我没有将参数传递给另一个函数,而是直接使用它。但是后来我想即使我直接使用它,例如通过分配它,或者将它用作构造函数参数,那么每个都是函数调用,分别是 operator=
和构造函数,这是一个函数调用:
template <typename element_T>
void push_back(element_t&& copy)
{
*_end = copy; // This calls operator=, which is a function
}
template <typename ... ConstructorArgs>
void emplace_back(ConstructorArgs&& ... args)
{
new (_end) element_t(args);
// Calls constructor, needs (std::forward<ConstructorArgs>(args)...) ?
}
在这些情况下我需要调用 std::forward
吗?
作为变量名称的表达式始终是左值。例如,在
1 template <typename T>
2 void push_back(T&& copy) {
3 *_end = copy;
4 }
第 3 行中的 copy
具有左值 value category,无论 T
推导的是什么类型。根据第 3 行中的 operator=
是 defined/overloaded 的方式,这可能会导致选择错误的重载或错误的类型推导。
考虑以下简单示例(遵循评论部分中 Ted Lyngmo 的示例):
struct A {
void operator=(const A&); // (1)
void operator=(A&&); // (2)
};
struct C {
template<class T>
void push_back(T&& copy) {
a = copy;
}
A a;
};
C{}.push_back(A{});
这里会调用哪个A
的赋值运算符?人们可能期望 (2) 因为 A{}
是纯右值,但正确答案是 (1),因为 copy
,并且左值不能绑定到右值引用。
如果我们将分配更改为
a = std::forward<T>(copy);
然后表达式 std::forward<T>(copy)
将具有 xvalue 值类别,并且将按预期调用 (2) 赋值运算符。
新的展示位置遵循相同的推理。
我心想,我的函数中不需要 std::forward<T>(arg);
,因为我没有将参数传递给另一个函数,而是直接使用它。但是后来我想即使我直接使用它,例如通过分配它,或者将它用作构造函数参数,那么每个都是函数调用,分别是 operator=
和构造函数,这是一个函数调用:
template <typename element_T>
void push_back(element_t&& copy)
{
*_end = copy; // This calls operator=, which is a function
}
template <typename ... ConstructorArgs>
void emplace_back(ConstructorArgs&& ... args)
{
new (_end) element_t(args);
// Calls constructor, needs (std::forward<ConstructorArgs>(args)...) ?
}
在这些情况下我需要调用 std::forward
吗?
作为变量名称的表达式始终是左值。例如,在
1 template <typename T>
2 void push_back(T&& copy) {
3 *_end = copy;
4 }
第 3 行中的 copy
具有左值 value category,无论 T
推导的是什么类型。根据第 3 行中的 operator=
是 defined/overloaded 的方式,这可能会导致选择错误的重载或错误的类型推导。
考虑以下简单示例(遵循评论部分中 Ted Lyngmo 的示例):
struct A {
void operator=(const A&); // (1)
void operator=(A&&); // (2)
};
struct C {
template<class T>
void push_back(T&& copy) {
a = copy;
}
A a;
};
C{}.push_back(A{});
这里会调用哪个A
的赋值运算符?人们可能期望 (2) 因为 A{}
是纯右值,但正确答案是 (1),因为 copy
如果我们将分配更改为
a = std::forward<T>(copy);
然后表达式 std::forward<T>(copy)
将具有 xvalue 值类别,并且将按预期调用 (2) 赋值运算符。
新的展示位置遵循相同的推理。