swap temporary tuples of references

c++, rvalue, swap, tuples

Solution

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; }

Usage:

std::swap(stay(foo()), stay(bar()));

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]); } }

Problem

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. 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))); } ```

Original source

Related problems