swap temporary tuples of references

醉酒当歌 提交于 2019-12-04 06:56:23
Kerrek SB

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

The answer I came up with was to write a tuple wrapper class:

template<typename ... Types>
struct tupleWrapper{
   std::tuple<Types...> data;
   tupleWrapper(std::tuple<Types...> _data) : data{_data}
   {}
   operator std::tuple<Types...> () {return data;}
   std::tuple<Types...>& asTuple() {return data;}
 };

template<typename ... Types>
void swap(tupleWrapper<Types ...> t1, tupleWrapper<Types ...> t2){
  std::swap(t1.data, t2.data);
}

And a get function that can be found with ADL, since the conversion operator doesn't get called when doing TAD for std::get.

template<int N, typename ...Ts>
  auto get(tupleWrapper<Ts...> tw)->decltype(std::get<N>(tw.data)){
    return std::get<N>(tw.data);
}

It's not ideal, but I think it will work well enough.

You can place the std::tuple as a data member and return a reference to that:

class iterator
{
public:
    iterator(std::vector<int>& _v1,
             std::vector<int>& _v2)
      : tup(_v1[5], _v2[5]) {}

    tuple_of_references& operator*() const
    {
        return tup;
    }
private:
    typedef std::tuple<int&, int&> tuple_of_references; // just to cut down size
    tuple_of_references tup;
};
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!