交换引用的临时元组
我正在编写一个自定义迭代器,它在取消引用时会返回一个引用元组.由于元组本身是短暂的,我认为我不能从 operator*() 返回引用.我认为我的迭代器在语义上是有意义的,因为它具有引用语义,即使 operator* 返回一个值.
I'm writing a custom iterator that, when dereferenced returns a tuple of references. Since the tuple itself is ephemeral, I don't think I can return a reference from operator*(). I think my iterator makes sense semantically, since it has reference semantics, even though operator* returns a value.
问题是,当我尝试调用 std::swap 时(或者更确切地说,当 std::sort 调用时),如下所示,我收到错误,因为交换需要 l 值.这个问题有简单的解决方法吗?
The issue is, when I try to call std::swap (or rather, when std::sort does), like below, I get errors because the swap expects l-values. Is there an easy fix to this problem?
#include <vector>
class test {
public:
test()
:v1(10), v2(10)
{}
class iterator {
public:
iterator(std::vector<int>& _v1,
std::vector<int>& _v2)
:v1(_v1), v2(_v2){}
std::tuple<int&, int&> operator*(){
return std::tuple<int&, int&>{v1[5], v2[5]};
}
std::vector<int>& v1;
std::vector<int>& v2;
};
std::vector<int> v1, v2;
};
int main(){
test t;
//error, Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/c++/v1/type_traits:3003:1: note: candidate function [with _Tp = std::__1::tuple<int &, int &>] not viable: expects an l-value for 1st argument
//deep within the bowels of std::sort ...
std::swap(*(test::iterator(t.v1, t.v2)),
*(test::iterator(t.v1, t.v2)));
}
推荐答案
在极少数情况上可能希望得到对临时的左值引用.这很容易通过与 std::move
:
On rare occasions it may be desirable to get an lvalue reference to temporary. This easily achieved with a cast opposite to std::move
:
template <typename T>
T & stay(T && t) { return t; }
用法:
std::swap(stay(foo()), stay(bar()));
<小时>
正如您已经说过的,如果您无法更改调用站点,您最好的选择可能是编写自己的引用包装器并为此使用 ADL:
As you already said, if you can't change the call site, your best option may be to write your own reference wrapper and use ADL for that:
namespace detail
{
struct IntRefPair
{
int & a, & b;
IntRefPair(int & x, int & y) : a(x), b(y) {}
};
void swap(IntRefPair && lhs, IntRefPair && rhs)
{
std::swap(lhs.a, rhs.a);
std::swap(lhs.b, rhs.b);
}
}
// ...
IntRefPair operator*() { return IntRefPair(v1[5], v2[5]); } }
相关文章