【发布时间】:2023-03-02 23:44:01
【问题描述】:
我希望围绕 std::make_pair 创建一个包装器,它接受一个参数并使用该参数来生成该对的第一个和第二个成员。此外,我希望利用移动语义。
天真地,我们可能会写(为了清楚起见忽略返回类型),
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
std::forward<T>(t));
}
但这不太可能达到我们想要的效果。
我们想要的是:
- 在使用 (const) 左值引用参数调用 foo 的情况下,我们应该将该 (const) 引用传递给 std::make_pair 而不修改两个参数。
- 在使用右值引用参数调用 foo 的情况下,我们应该复制被引用的对象,然后使用原始右值引用以及对新创建对象的右值引用调用 std::make_pair。
到目前为止,我想出的是:
template <typename T>
T forward_or_duplicate(T t)
{
return t;
}
template <typename T>
void foo(T&& t)
{
std::make_pair(std::forward<T>(t),
forward_or_duplicate<T>(t));
}
但我有理由确定这是错误的。
所以,问题:
这行得通吗?我怀疑不是因为如果使用右值引用调用 foo() 则在构造按值传递给 forward_or_duplicate() 的 T 时将调用 T 的移动构造函数(如果存在),从而破坏 t。
即使它确实有效,它是最优的吗?同样,我怀疑不会在从 forward_or_duplicate() 返回 t 时调用 T 的复制构造函数。
这似乎是一个常见问题。有没有惯用的解决方案?
【问题讨论】:
-
如果参数评估之间的顺序已定义(不幸的是,它没有),我认为您只需
std::make_pair(t, std::forward<T>(t))就可以做到这一点。 -
@KerrekSB:哈,没想到。你应该提交一个答案:-)
-
其实我看不出
forward_or_duplicate有什么问题。 -
@KerrekSB 我没看到。
make_pair通过引用获取参数,因此移动发生在其中,复制发生在您输入make_pair之前。 -
@KerrekSB 它转发左值,并复制右值。
标签: c++ c++11 perfect-forwarding